ValueSet cleanup (#4227)
* POST release deferred cleanup * Fixes * One more test fix * Test fixes * Test fixes * Test cleanup * Test fixes * Fixes * ValueSet cleanup * Test fix * Test fixes * Fixes * Test fixes * Fixed * Test fixes * Test fixes * Test fixes * Test fixes * Test fixc * Build fix * Fix merge artifact * Build fix * Work on tests * Test fixes * Work * Fixes * Changelog fix * Add changelog * Test fix * Test fixes * Fixes * Test fixes * Test fixes * Test fixes * Test fix * Tests * Bumps * Fixes * Add errorprone * Drop bz2 bins * POM fix * Build fix * Update * Test fix Co-authored-by: James Agnew <james@jamess-mbp.lan>
This commit is contained in:
parent
d3367cfede
commit
b3ebbe7933
|
@ -19,6 +19,9 @@ ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamString/
|
|||
ca.uhn.fhir.jpa.entity.ResourceTable/
|
||||
ca.uhn.fhir.jpa.entity.TermConcept/
|
||||
|
||||
# Ignore Java Heap Dumps
|
||||
java_pid*.*
|
||||
|
||||
# Vagrant stuff.
|
||||
.vagrant
|
||||
/vagrant/build
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -126,12 +126,11 @@
|
|||
<execution>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>checkstyle</goal>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<failsOnError>true</failsOnError>
|
||||
<enableRulesSummary>true</enableRulesSummary>
|
||||
<enableSeveritySummary>true</enableSeveritySummary>
|
||||
<logViolationsToConsole>true</logViolationsToConsole>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<configLocation>${maven.multiModuleProjectDirectory}/src/checkstyle/checkstyle.xml</configLocation>
|
||||
</configuration>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -394,8 +394,9 @@ public class FhirContext {
|
|||
return myNarrativeGenerator;
|
||||
}
|
||||
|
||||
public void setNarrativeGenerator(final INarrativeGenerator theNarrativeGenerator) {
|
||||
public FhirContext setNarrativeGenerator(final INarrativeGenerator theNarrativeGenerator) {
|
||||
myNarrativeGenerator = theNarrativeGenerator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -325,9 +325,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
|||
|
||||
private void loadStructureDefinitions(Map<String, IBaseResource> theCodeSystems, String theClasspath) {
|
||||
ourLog.info("Loading structure definitions from classpath: {}", theClasspath);
|
||||
try (InputStream valuesetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath)) {
|
||||
if (valuesetText != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(valuesetText, Constants.CHARSET_UTF8)) {
|
||||
try (InputStream valueSetText = DefaultProfileValidationSupport.class.getResourceAsStream(theClasspath)) {
|
||||
if (valueSetText != null) {
|
||||
try (InputStreamReader reader = new InputStreamReader(valueSetText, Constants.CHARSET_UTF8)) {
|
||||
|
||||
List<IBaseResource> resources = parseBundle(reader);
|
||||
for (IBaseResource next : resources) {
|
||||
|
|
|
@ -181,7 +181,11 @@ public abstract class BaseInterceptorService<POINTCUT extends IPointcut> impleme
|
|||
|
||||
private void unregisterInterceptorsIf(Predicate<Object> theShouldUnregisterFunction, ListMultimap<POINTCUT, BaseInvoker> theGlobalInvokers) {
|
||||
synchronized (myRegistryMutex) {
|
||||
theGlobalInvokers.entries().removeIf(t -> theShouldUnregisterFunction.test(t.getValue().getInterceptor()));
|
||||
for (Map.Entry<POINTCUT, BaseInvoker> nextInvoker : new ArrayList<>(theGlobalInvokers.entries())) {
|
||||
if (theShouldUnregisterFunction.test(nextInvoker.getValue().getInterceptor())) {
|
||||
unregisterInterceptor(nextInvoker.getValue().getInterceptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
package ca.uhn.fhir.util;
|
||||
|
||||
/*
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
|
@ -20,17 +20,15 @@ package ca.uhn.fhir.jpa.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
|
||||
public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResourceProvider<T> {
|
||||
|
||||
public JpaResourceProviderDstu2() {
|
||||
// nothing
|
||||
/**
|
||||
* Exception superclass for an exception representing an unrecoverable failure
|
||||
*/
|
||||
public abstract class BaseUnrecoverableRuntimeException extends RuntimeException {
|
||||
public BaseUnrecoverableRuntimeException(String theMessage) {
|
||||
super(theMessage);
|
||||
}
|
||||
|
||||
public JpaResourceProviderDstu2(IFhirResourceDao<T> theDao) {
|
||||
super(theDao);
|
||||
public BaseUnrecoverableRuntimeException(String theMessage, Throwable theCause) {
|
||||
super(theMessage, theCause);
|
||||
}
|
||||
|
||||
}
|
|
@ -61,4 +61,12 @@ public class DatatypeUtil {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link IPrimitiveType#getValueAsString()} if <code>thePrimitiveType</code> is
|
||||
* not null, else returns null.
|
||||
*/
|
||||
public static String toStringValue(IPrimitiveType<?> thePrimitiveType) {
|
||||
return thePrimitiveType != null ? thePrimitiveType.getValueAsString() : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-batch</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HAPI FHIR JPA Server - Batch Task Processor</name>
|
||||
<description>Default implementation of batch job submitter along with constants used by the different hapi-fhir batch
|
||||
jobs.
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--test dependencies -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-base</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- test -->
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-test-utilities</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipDeploy>true</skipDeploy>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
|
@ -3,14 +3,14 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,8 +18,6 @@
|
|||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<!-- FIXME move version up -->
|
||||
<version>8.43</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -78,10 +78,6 @@
|
|||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
|
@ -177,11 +173,15 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-api</artifactId>
|
||||
<artifactId>websocket-jetty-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-client</artifactId>
|
||||
<artifactId>websocket-core-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-jetty-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
|
|
@ -25,9 +25,14 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.eclipse.jetty.websocket.api.Frame;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.annotations.*;
|
||||
import org.eclipse.jetty.websocket.api.extensions.Frame;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -1818,7 +1818,7 @@ public class GenericOkHttpClientDstu2Test {
|
|||
@Override
|
||||
public void handle(String theArg0, Request theRequest, HttpServletRequest theServletRequest, HttpServletResponse theResp) throws IOException, ServletException {
|
||||
theRequest.setHandled(true);
|
||||
ourRequestUri = "http:" + theRequest.getHttpURI().toString();
|
||||
ourRequestUri = theRequest.getHttpURI().toString();
|
||||
ourRequestUriAll.add(ourRequestUri);
|
||||
ourRequestMethod = theRequest.getMethod();
|
||||
ourRequestContentType = theServletRequest.getContentType();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -79,7 +79,10 @@ public class VersionCanonicalizer {
|
|||
public VersionCanonicalizer(FhirVersionEnum theTargetVersion) {
|
||||
switch (theTargetVersion) {
|
||||
case DSTU2:
|
||||
myStrategy = new Dstu2Strategy();
|
||||
myStrategy = new Dstu2Strategy(false);
|
||||
break;
|
||||
case DSTU2_HL7ORG:
|
||||
myStrategy = new Dstu2Strategy(true);
|
||||
break;
|
||||
case DSTU3:
|
||||
myStrategy = new Dstu3Strategy();
|
||||
|
@ -179,6 +182,11 @@ public class VersionCanonicalizer {
|
|||
private final FhirContext myDstu2Hl7OrgContext = FhirContext.forDstu2Hl7OrgCached();
|
||||
|
||||
private final FhirContext myDstu2Context = FhirContext.forDstu2Cached();
|
||||
private final boolean myHl7OrgStructures;
|
||||
|
||||
public Dstu2Strategy(boolean theHl7OrgStructures) {
|
||||
myHl7OrgStructures = theHl7OrgStructures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CapabilityStatement capabilityStatementToCanonical(ca.uhn.fhir.model.dstu2.resource.BaseResource theCapabilityStatement) {
|
||||
|
@ -216,7 +224,8 @@ public class VersionCanonicalizer {
|
|||
@Override
|
||||
public ValueSet valueSetToCanonical(IBaseResource theValueSet) {
|
||||
org.hl7.fhir.dstu2.model.Resource reencoded = reencodeToHl7Org(theValueSet);
|
||||
return (ValueSet) VersionConvertorFactory_10_40.convertResource(reencoded, ADVISOR_10_40);
|
||||
ValueSet valueSet = (ValueSet) VersionConvertorFactory_10_40.convertResource(reencoded, ADVISOR_10_40);
|
||||
return valueSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -267,10 +276,16 @@ public class VersionCanonicalizer {
|
|||
}
|
||||
|
||||
private Resource reencodeToHl7Org(IBaseResource theInput) {
|
||||
if (myHl7OrgStructures) {
|
||||
return (Resource) theInput;
|
||||
}
|
||||
return (Resource) myDstu2Hl7OrgContext.newJsonParser().parseResource(myDstu2Context.newJsonParser().encodeResourceToString(theInput));
|
||||
}
|
||||
|
||||
private IBaseResource reencodeFromHl7Org(Resource theInput) {
|
||||
if (myHl7OrgStructures) {
|
||||
return theInput;
|
||||
}
|
||||
return myDstu2Context.newJsonParser().parseResource(myDstu2Hl7OrgContext.newJsonParser().encodeResourceToString(theInput));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import ca.uhn.fhir.context.FhirVersionEnum;
|
|||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
@ -19,5 +20,4 @@ class VersionCanonicalizerTest {
|
|||
assertEquals("dstuSystem", convertedCoding.getSystem());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -9,37 +9,6 @@
|
|||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<logger name="ca.uhn.fhir.jpa.dao.FhirResourceDaoSubscriptionDstu2" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.eclipse.jetty.websocket" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.eclipse" additivity="false" level="error">
|
||||
</logger>
|
||||
|
||||
<logger name="ca.uhn.fhir.rest.client" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<logger name="ca.uhn.fhir.jpa.dao" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<!-- Set to 'trace' to enable SQL logging -->
|
||||
<logger name="org.hibernate.SQL" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
<!-- Set to 'trace' to enable SQL Value logging -->
|
||||
<logger name="org.hibernate.type" additivity="false" level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</logger>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
<format>tar.bz2</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
|
||||
<id>jpaserver-example</id>
|
||||
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
<format>tar.bz2</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/../hapi-fhir-jpaserver-example</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>pom.xml</include>
|
||||
<include>src/**</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
||||
</assembly>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
|
||||
<id>jpaserver-example</id>
|
||||
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}/../hapi-fhir-jpaserver-example</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>pom.xml</include>
|
||||
<include>src/**</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
||||
</assembly>
|
||||
|
|
|
@ -1,52 +1,51 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
|
||||
<id>standard-distribution</id>
|
||||
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
<format>tar.bz2</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>README*</include>
|
||||
<include>LICENSE*</include>
|
||||
<include>NOTICE*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<outputDirectory>/lib</outputDirectory>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<unpack>false</unpack>
|
||||
<scope>runtime</scope>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<outputDirectory>/src</outputDirectory>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<unpack>false</unpack>
|
||||
<includes>
|
||||
<include>*:hapi*:jar:sources:*</include>
|
||||
</includes>
|
||||
<scope>provided</scope>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<outputDirectory>/javadoc</outputDirectory>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<unpack>false</unpack>
|
||||
<includes>
|
||||
<include>*:hapi*:jar:javadoc:*</include>
|
||||
</includes>
|
||||
<scope>provided</scope>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
|
||||
</assembly>
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
|
||||
<id>standard-distribution</id>
|
||||
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.basedir}</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<includes>
|
||||
<include>README*</include>
|
||||
<include>LICENSE*</include>
|
||||
<include>NOTICE*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<outputDirectory>/lib</outputDirectory>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<unpack>false</unpack>
|
||||
<scope>runtime</scope>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<outputDirectory>/src</outputDirectory>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<unpack>false</unpack>
|
||||
<includes>
|
||||
<include>*:hapi*:jar:sources:*</include>
|
||||
</includes>
|
||||
<scope>provided</scope>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<outputDirectory>/javadoc</outputDirectory>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<unpack>false</unpack>
|
||||
<includes>
|
||||
<include>*:hapi*:jar:javadoc:*</include>
|
||||
</includes>
|
||||
<scope>provided</scope>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
|
||||
</assembly>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
type: change
|
||||
issue: 4221
|
||||
title: "The JPA server implementation of the $process-message operation has been extracted into
|
||||
a standalone provider called `ProcessMessageProvider` which can be registered individually
|
||||
on servers that have provided an implementation of the backing operation. Because this operation
|
||||
can not be implemented in a generic was in HAPI FHIR (it assumes business-specific processing
|
||||
logic) it does not make sense to include it by default."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: add
|
||||
issue: 4227
|
||||
title: "The internal LinkedChannelQueue implementation used for Batch2 processing and Subscription delivery
|
||||
now uses automated retries if a message processing failure occurs in order to improve resiliency."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: add
|
||||
issue: 4227
|
||||
title: "When indexing CodeSystem content in the terminology service, an unintended busy-wait cycle sometimes caused the
|
||||
CPU to be thrashed while waiting for a batch job to complete. This has been resolved."
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: add
|
||||
issue: 4227
|
||||
title: "In some cases in the JPA server, CodeSystem updating failed and left the server with a hung
|
||||
reindex job that never completes. This has been corrected. Thanks to GitHub user @tyfoni-systematic for
|
||||
the bug report!"
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
type: add
|
||||
issue: 4227
|
||||
title: "When validating terminology as a part of resource validation or by directly calling the $validate-code
|
||||
operations, an incorrect caching routine sometimes caused incorrect cached results to be returned in cases
|
||||
where display names are being validated and multiple display names were validated for the same
|
||||
system+code combination. This has been corrected."
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
- item:
|
||||
type: "add"
|
||||
title: "The version of a few dependencies have been bumped to the latest versions
|
||||
(dependent HAPI modules listed in brackets):
|
||||
<ul>
|
||||
<li>SLF4j (All): 1.7.33 -> 2.0.3</li>
|
||||
<li>Logback (All): 1.2.10 -> 1.4.4</li>
|
||||
<li>Jetty (CLI): 9.4.48.v20220622 -> 10.0.12</li>
|
||||
<li>Spring Boot: 2.7.4 -> 2.7.5</li>
|
||||
</ul>
|
||||
In addition the following dependencies have been replaced with newer equivalents:
|
||||
<ul>
|
||||
<li>
|
||||
javax.annotation:javax.annotation-api:1.3.2 ->
|
||||
jakarta.annotation:jakarta.annotation-api:1.3.3 –
|
||||
This change brings HAPI FHIR up to the new permanent Maven dependency name for
|
||||
this library. Note that this new version does not change the actual package
|
||||
structure of the included classes from <code>javax.</code> to <code>jakarta.</code>,
|
||||
it is only a change in the Maven packaging.
|
||||
</li>
|
||||
<li>
|
||||
javax.transaction:javax.transaction-api:1.3.2 ->
|
||||
jakarta.transaction:jakarta.transaction-api:1.3.5 –
|
||||
This change brings HAPI FHIR up to the new permanent Maven dependency name for
|
||||
this library. Note that this new version does not change the actual package
|
||||
structure of the included classes from <code>javax.</code> to <code>jakarta.</code>,
|
||||
it is only a change in the Maven packaging.
|
||||
</li>
|
||||
</ul>
|
||||
"
|
||||
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-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.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -87,12 +87,6 @@
|
|||
<artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Unit test dependencies -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.woodstox</groupId>
|
||||
|
|
|
@ -2032,7 +2032,7 @@ public class GenericJaxRsClientDstu2Test {
|
|||
@Override
|
||||
public void handle(String theArg0, Request theRequest, HttpServletRequest theServletRequest, HttpServletResponse theResp) throws IOException {
|
||||
theRequest.setHandled(true);
|
||||
ourRequestUri = "http:" + theRequest.getHttpURI().toString();
|
||||
ourRequestUri = theRequest.getHttpURI().toString();
|
||||
ourRequestUriAll.add(ourRequestUri);
|
||||
ourRequestMethod = theRequest.getMethod();
|
||||
ourRequestContentType = theServletRequest.getContentType();
|
||||
|
|
|
@ -2121,7 +2121,7 @@ public class GenericJaxRsClientDstu3Test {
|
|||
@Override
|
||||
public void handle(String theArg0, Request theRequest, HttpServletRequest theServletRequest, HttpServletResponse theResp) throws IOException {
|
||||
theRequest.setHandled(true);
|
||||
ourRequestUri = "http:" + theRequest.getHttpURI().toString();
|
||||
ourRequestUri = theRequest.getHttpURI().toString();
|
||||
ourRequestUriAll.add(ourRequestUri);
|
||||
ourRequestMethod = theRequest.getMethod();
|
||||
ourRequestContentType = theServletRequest.getContentType();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -21,10 +21,6 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</dependency>
|
||||
<!-- for date logging -->
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
|
@ -32,6 +28,11 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Hibernate -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
|
|
|
@ -229,13 +229,18 @@ public class CircularQueueCaptureQueriesListener extends BaseCaptureQueriesListe
|
|||
.map(CircularQueueCaptureQueriesListener::formatQueryAsSql)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> newList = new ArrayList<>();
|
||||
if (theIndexes != null && theIndexes.length > 0) {
|
||||
List<String> newList = new ArrayList<>();
|
||||
for (int i = 0; i < theIndexes.length; i++) {
|
||||
newList.add(queries.get(theIndexes[i]));
|
||||
int index = theIndexes[i];
|
||||
newList.add("[" + index + "] " + queries.get(index));
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < queries.size(); i++) {
|
||||
newList.add("[" + i + "] " + queries.get(i));
|
||||
}
|
||||
queries = newList;
|
||||
}
|
||||
queries = newList;
|
||||
|
||||
String queriesAsString = String.join("\n", queries);
|
||||
ourLog.info("Select Queries:\n{}", queriesAsString);
|
||||
|
@ -382,14 +387,14 @@ public class CircularQueueCaptureQueriesListener extends BaseCaptureQueriesListe
|
|||
public int countInsertQueries() {
|
||||
return getInsertQueries()
|
||||
.stream()
|
||||
.map(t->t.getSize())
|
||||
.map(t -> t.getSize())
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
public int countUpdateQueries() {
|
||||
return getUpdateQueries()
|
||||
.stream()
|
||||
.map(t->t.getSize())
|
||||
.map(t -> t.getSize())
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
|
@ -404,6 +409,11 @@ public class CircularQueueCaptureQueriesListener extends BaseCaptureQueriesListe
|
|||
return getSelectQueriesForCurrentThread().size();
|
||||
}
|
||||
|
||||
// TODO: JA2 The count "forCurrentThread" methods work differently than the non
|
||||
// current thread ones - The other ones aggregate multiple instances of the same
|
||||
// query - In other words if the same query is issued twice with different parameters
|
||||
// that counts for 2 on the other method but 1 for this one. Need to harmonize this,
|
||||
// and should do it on this method since the higher number is more accurate.
|
||||
public int countInsertQueriesForCurrentThread() {
|
||||
return getInsertQueriesForCurrentThread().size();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -57,6 +57,11 @@
|
|||
<artifactId>hapi-fhir-server-mdm</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-storage</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-subscription</artifactId>
|
||||
|
@ -132,11 +137,6 @@
|
|||
<artifactId>hapi-fhir-validation-resources-r5</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-batch</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-storage-batch2</artifactId>
|
||||
|
@ -158,6 +158,10 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ttddyy</groupId>
|
||||
<artifactId>datasource-proxy</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
|
@ -247,11 +251,6 @@
|
|||
<!--
|
||||
Dependencies that need to be added since JDK9
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
|
@ -354,6 +353,10 @@
|
|||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
|
@ -375,6 +378,12 @@
|
|||
<groupId>org.apache.jena</groupId>
|
||||
<artifactId>jena-arq</artifactId>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jena</groupId>
|
||||
|
|
|
@ -239,6 +239,7 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
|
|||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void markWorkChunkAsFailed(String theChunkId, String theErrorMessage) {
|
||||
ourLog.info("Marking chunk {} as failed with message: {}", theChunkId, theErrorMessage);
|
||||
String errorMessage;
|
||||
if (theErrorMessage.length() > Batch2WorkChunkEntity.ERROR_MSG_MAX_LENGTH) {
|
||||
ourLog.warn("Truncating error message that is too long to store in database: {}", theErrorMessage);
|
||||
|
@ -353,6 +354,7 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
|
|||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void deleteInstanceAndChunks(String theInstanceId) {
|
||||
ourLog.info("Deleting instance and chunks: {}", theInstanceId);
|
||||
myWorkChunkRepository.deleteAllForInstance(theInstanceId);
|
||||
myJobInstanceRepository.deleteById(theInstanceId);
|
||||
}
|
||||
|
@ -360,6 +362,7 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
|
|||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void deleteChunks(String theInstanceId) {
|
||||
ourLog.info("Deleting all chunks for instance ID: {}", theInstanceId);
|
||||
myWorkChunkRepository.deleteAllForInstance(theInstanceId);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.config;
|
|||
|
||||
import ca.uhn.fhir.batch2.jobs.expunge.DeleteExpungeJobSubmitterImpl;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorService;
|
||||
|
@ -61,9 +62,12 @@ import ca.uhn.fhir.jpa.partition.PartitionLookupSvcImpl;
|
|||
import ca.uhn.fhir.jpa.partition.PartitionManagementProvider;
|
||||
import ca.uhn.fhir.jpa.partition.RequestPartitionHelperSvc;
|
||||
import ca.uhn.fhir.jpa.provider.DiffProvider;
|
||||
import ca.uhn.fhir.jpa.provider.ValueSetOperationProvider;
|
||||
import ca.uhn.fhir.jpa.provider.ProcessMessageProvider;
|
||||
import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
|
||||
import ca.uhn.fhir.jpa.provider.TerminologyUploaderProvider;
|
||||
import ca.uhn.fhir.jpa.provider.ValueSetOperationProvider;
|
||||
import ca.uhn.fhir.jpa.provider.ValueSetOperationProviderDstu2;
|
||||
import ca.uhn.fhir.jpa.provider.r4.IConsentExtensionProvider;
|
||||
import ca.uhn.fhir.jpa.provider.r4.MemberMatcherR4Helper;
|
||||
import ca.uhn.fhir.jpa.sched.AutowiringSpringBeanJobFactory;
|
||||
|
@ -250,7 +254,10 @@ public class JpaConfig {
|
|||
|
||||
@Bean
|
||||
@Lazy
|
||||
public ValueSetOperationProvider valueSetOperationProvider() {
|
||||
public ValueSetOperationProvider valueSetOperationProvider(FhirContext theFhirContext) {
|
||||
if (theFhirContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||
return new ValueSetOperationProviderDstu2();
|
||||
}
|
||||
return new ValueSetOperationProvider();
|
||||
}
|
||||
|
||||
|
@ -417,6 +424,12 @@ public class JpaConfig {
|
|||
return new TerminologyUploaderProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public ProcessMessageProvider processMessageProvider() {
|
||||
return new ProcessMessageProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ISchedulerService schedulerService() {
|
||||
return new HapiSchedulerServiceImpl().setDefaultGroup(HAPI_DEFAULT_SCHEDULER_GROUP);
|
||||
|
|
|
@ -21,20 +21,20 @@ package ca.uhn.fhir.jpa.config.dstu3;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.ParserOptions;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import static ca.uhn.fhir.jpa.config.r4.FhirContextR4Config.configureFhirContext;
|
||||
|
||||
public class FhirContextDstu3Config {
|
||||
@Primary
|
||||
@Bean(name = "primaryFhirContext")
|
||||
public FhirContext fhirContextDstu3() {
|
||||
FhirContext retVal = FhirContext.forDstu3();
|
||||
|
||||
// Don't strip versions in some places
|
||||
ParserOptions parserOptions = retVal.getParserOptions();
|
||||
parserOptions.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference");
|
||||
configureFhirContext(retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,23 +21,38 @@ package ca.uhn.fhir.jpa.config.r4;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.ParserOptions;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
public class FhirContextR4Config {
|
||||
|
||||
public static final String DEFAULT_PRESERVE_VERSION_REFS = "AuditEvent.entity.what";
|
||||
public static final String DEFAULT_PRESERVE_VERSION_REFS_DSTU2 = "AuditEvent.object.reference";
|
||||
public static final String DEFAULT_PRESERVE_VERSION_REFS_DSTU3 = "AuditEvent.entity.reference";
|
||||
public static final String DEFAULT_PRESERVE_VERSION_REFS_R4_AND_LATER = "AuditEvent.entity.what";
|
||||
|
||||
@Bean(name = "primaryFhirContext")
|
||||
@Primary
|
||||
public FhirContext fhirContextR4() {
|
||||
FhirContext retVal = FhirContext.forR4();
|
||||
|
||||
// Don't strip versions in some places
|
||||
ParserOptions parserOptions = retVal.getParserOptions();
|
||||
parserOptions.setDontStripVersionsFromReferencesAtPaths(DEFAULT_PRESERVE_VERSION_REFS);
|
||||
configureFhirContext(retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static FhirContext configureFhirContext(FhirContext theFhirContext) {
|
||||
// Don't strip versions in some places
|
||||
ParserOptions parserOptions = theFhirContext.getParserOptions();
|
||||
if (theFhirContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
|
||||
parserOptions.setDontStripVersionsFromReferencesAtPaths(DEFAULT_PRESERVE_VERSION_REFS_DSTU2);
|
||||
} else if (theFhirContext.getVersion().getVersion().equals(FhirVersionEnum.DSTU3)) {
|
||||
parserOptions.setDontStripVersionsFromReferencesAtPaths(DEFAULT_PRESERVE_VERSION_REFS_DSTU3);
|
||||
} else {
|
||||
parserOptions.setDontStripVersionsFromReferencesAtPaths(DEFAULT_PRESERVE_VERSION_REFS_R4_AND_LATER);
|
||||
}
|
||||
|
||||
return theFhirContext;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,23 +21,21 @@ package ca.uhn.fhir.jpa.config.r4b;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.ParserOptions;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
public class FhirContextR4BConfig {
|
||||
import static ca.uhn.fhir.jpa.config.r4.FhirContextR4Config.configureFhirContext;
|
||||
|
||||
public static final String DEFAULT_PRESERVE_VERSION_REFS = "AuditEvent.entity.what";
|
||||
public class FhirContextR4BConfig {
|
||||
|
||||
@Bean(name = "primaryFhirContext")
|
||||
@Primary
|
||||
public FhirContext fhirContextR4B() {
|
||||
FhirContext retVal = FhirContext.forR4B();
|
||||
|
||||
// Don't strip versions in some places
|
||||
ParserOptions parserOptions = retVal.getParserOptions();
|
||||
parserOptions.setDontStripVersionsFromReferencesAtPaths(DEFAULT_PRESERVE_VERSION_REFS);
|
||||
configureFhirContext(retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,20 +21,20 @@ package ca.uhn.fhir.jpa.config.r5;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.ParserOptions;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import static ca.uhn.fhir.jpa.config.r4.FhirContextR4Config.configureFhirContext;
|
||||
|
||||
public class FhirContextR5Config {
|
||||
@Bean(name = "primaryFhirContext")
|
||||
@Primary
|
||||
public FhirContext fhirContextR5() {
|
||||
FhirContext retVal = FhirContext.forR5();
|
||||
|
||||
// Don't strip versions in some places
|
||||
ParserOptions parserOptions = retVal.getParserOptions();
|
||||
parserOptions.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.what");
|
||||
configureFhirContext(retVal);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoMessageHeader;
|
||||
import ca.uhn.fhir.model.dstu2.resource.MessageHeader;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
||||
public class FhirResourceDaoMessageHeaderDstu2 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||
|
||||
public static IBaseBundle throwProcessMessageNotImplemented() {
|
||||
throw new NotImplementedOperationException(Msg.code(945) + "This operation is not yet implemented on this server");
|
||||
}
|
||||
}
|
|
@ -1,321 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ComposeInclude;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ComposeIncludeConcept;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet.ExpansionContains;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.PostConstruct;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
|
||||
import static ca.uhn.fhir.jpa.util.LogicUtil.multiXor;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class FhirResourceDaoValueSetDstu2 extends BaseHapiFhirResourceDao<ValueSet>
|
||||
implements IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>, IFhirResourceDaoCodeSystem<ValueSet, CodingDt, CodeableConceptDt> {
|
||||
|
||||
private static FhirContext ourRiCtx;
|
||||
|
||||
private DefaultProfileValidationSupport myDefaultProfileValidationSupport;
|
||||
|
||||
@Autowired
|
||||
private IValidationSupport myJpaValidationSupport;
|
||||
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
private CachingValidationSupport myValidationSupport;
|
||||
|
||||
private void addCompose(String theFilter, ValueSet theValueSetToPopulate, ValueSet theSourceValueSet, CodeSystemConcept theConcept) {
|
||||
if (isBlank(theFilter)) {
|
||||
addCompose(theValueSetToPopulate, theSourceValueSet.getCodeSystem().getSystem(), theConcept.getCode(), theConcept.getDisplay());
|
||||
} else {
|
||||
String filter = theFilter.toLowerCase();
|
||||
if (theConcept.getDisplay().toLowerCase().contains(filter) || theConcept.getCode().toLowerCase().contains(filter)) {
|
||||
addCompose(theValueSetToPopulate, theSourceValueSet.getCodeSystem().getSystem(), theConcept.getCode(), theConcept.getDisplay());
|
||||
}
|
||||
}
|
||||
for (CodeSystemConcept nextChild : theConcept.getConcept()) {
|
||||
addCompose(theFilter, theValueSetToPopulate, theSourceValueSet, nextChild);
|
||||
}
|
||||
}
|
||||
|
||||
private void addCompose(ValueSet retVal, String theSystem, String theCode, String theDisplay) {
|
||||
if (isBlank(theCode)) {
|
||||
return;
|
||||
}
|
||||
ExpansionContains contains = retVal.getExpansion().addContains();
|
||||
contains.setSystem(theSystem);
|
||||
contains.setCode(theCode);
|
||||
contains.setDisplay(theDisplay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequest) {
|
||||
ValueSet source = loadValueSetForExpansion(theId, theRequest);
|
||||
return expand(source, theOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet source, ValueSetExpansionOptions theOptions) {
|
||||
ValueSet retVal = new ValueSet();
|
||||
retVal.setDate(DateTimeDt.withCurrentTime());
|
||||
|
||||
|
||||
String filter = null;
|
||||
if (theOptions != null) {
|
||||
filter = theOptions.getFilter();
|
||||
}
|
||||
|
||||
/*
|
||||
* Add composed concepts
|
||||
*/
|
||||
|
||||
for (ComposeInclude nextInclude : source.getCompose().getInclude()) {
|
||||
for (ComposeIncludeConcept next : nextInclude.getConcept()) {
|
||||
if (isBlank(filter)) {
|
||||
addCompose(retVal, nextInclude.getSystem(), next.getCode(), next.getDisplay());
|
||||
} else {
|
||||
filter = filter.toLowerCase();
|
||||
if (next.getDisplay().toLowerCase().contains(filter) || next.getCode().toLowerCase().contains(filter)) {
|
||||
addCompose(retVal, nextInclude.getSystem(), next.getCode(), next.getDisplay());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add defined concepts
|
||||
*/
|
||||
|
||||
for (CodeSystemConcept next : source.getCodeSystem().getConcept()) {
|
||||
addCompose(filter, retVal, source, next);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) {
|
||||
if (isBlank(theUri)) {
|
||||
throw new InvalidRequestException(Msg.code(946) + "URI must not be blank or missing");
|
||||
}
|
||||
ValueSet source;
|
||||
|
||||
ValueSet defaultValueSet = myDefaultProfileValidationSupport.fetchResource(ValueSet.class, theUri);
|
||||
if (defaultValueSet != null) {
|
||||
source = getContext().newJsonParser().parseResource(ValueSet.class, getRiCtx().newJsonParser().encodeResourceToString(defaultValueSet));
|
||||
} else {
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
params.add(ValueSet.SP_URL, new UriParam(theUri));
|
||||
IBundleProvider ids = search(params);
|
||||
if (ids.size() == 0) {
|
||||
throw new InvalidRequestException(Msg.code(947) + "Unknown ValueSet URI: " + theUri);
|
||||
}
|
||||
source = (ValueSet) ids.getResources(0, 1).get(0);
|
||||
}
|
||||
|
||||
return expand(source, theOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
|
||||
if (theSystem != null && theSystem.startsWith("http://hl7.org/fhir/")) {
|
||||
return Collections.singletonList(new IdDt(theSystem));
|
||||
}
|
||||
|
||||
List<IIdType> valueSetIds;
|
||||
List<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(ValueSet.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
|
||||
valueSetIds = new ArrayList<>();
|
||||
for (ResourcePersistentId next : ids) {
|
||||
IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "ValueSet", next);
|
||||
valueSetIds.add(id);
|
||||
}
|
||||
return valueSetIds;
|
||||
}
|
||||
|
||||
private ValueSet loadValueSetForExpansion(IIdType theId, RequestDetails theRequest) {
|
||||
if (theId.getValue().startsWith("http://hl7.org/fhir/")) {
|
||||
org.hl7.fhir.dstu2.model.ValueSet valueSet = myValidationSupport.fetchResource(org.hl7.fhir.dstu2.model.ValueSet.class, theId.getValue());
|
||||
if (valueSet != null) {
|
||||
return getContext().newJsonParser().parseResource(ValueSet.class, getRiCtx().newJsonParser().encodeResourceToString(valueSet));
|
||||
}
|
||||
}
|
||||
BaseHasResource sourceEntity = readEntity(theId, theRequest);
|
||||
if (sourceEntity == null) {
|
||||
throw new ResourceNotFoundException(Msg.code(2002) + theId);
|
||||
}
|
||||
ValueSet source = (ValueSet) toResource(sourceEntity, false);
|
||||
return source;
|
||||
}
|
||||
|
||||
private FhirContext getRiCtx() {
|
||||
if (ourRiCtx == null) {
|
||||
ourRiCtx = FhirContext.forDstu2Hl7Org();
|
||||
}
|
||||
return ourRiCtx;
|
||||
}
|
||||
|
||||
private IValidationSupport.LookupCodeResult lookup(List<ExpansionContains> theContains, String theSystem, String theCode) {
|
||||
for (ExpansionContains nextCode : theContains) {
|
||||
|
||||
String system = nextCode.getSystem();
|
||||
String code = nextCode.getCode();
|
||||
if (theSystem.equals(system) && theCode.equals(code)) {
|
||||
IValidationSupport.LookupCodeResult retVal = new IValidationSupport.LookupCodeResult();
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
retVal.setFound(true);
|
||||
if (nextCode.getAbstract() != null) {
|
||||
retVal.setCodeIsAbstract(nextCode.getAbstract());
|
||||
}
|
||||
retVal.setCodeDisplay(nextCode.getDisplay());
|
||||
retVal.setCodeSystemVersion(nextCode.getVersion());
|
||||
retVal.setCodeSystemDisplayName("Unknown"); // TODO: implement
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Transactional
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, CodingDt theCoding, RequestDetails theRequest) {
|
||||
return lookupCode(theCode, theSystem, theCoding, null, theRequest);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Transactional
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, CodingDt theCoding, IPrimitiveType<String> theDisplayLanguage, RequestDetails theRequest) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
|
||||
if (!haveCoding && !(haveSystem && haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(949) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(950) + "$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
|
||||
}
|
||||
|
||||
String code;
|
||||
String system;
|
||||
if (haveCoding) {
|
||||
code = theCoding.getCode();
|
||||
system = theCoding.getSystem();
|
||||
} else {
|
||||
code = theCode.getValue();
|
||||
system = theSystem.getValue();
|
||||
}
|
||||
|
||||
List<IIdType> valueSetIds = findCodeSystemIdsContainingSystemAndCode(code, system, theRequest);
|
||||
for (IIdType nextId : valueSetIds) {
|
||||
ValueSet expansion = expand(nextId, null, theRequest);
|
||||
List<ExpansionContains> contains = expansion.getExpansion().getContains();
|
||||
IValidationSupport.LookupCodeResult result = lookup(contains, system, code);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
IValidationSupport.LookupCodeResult retVal = new IValidationSupport.LookupCodeResult();
|
||||
retVal.setFound(false);
|
||||
retVal.setSearchedForCode(code);
|
||||
retVal.setSearchedForSystem(system);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, CodingDt theCodingA, CodingDt theCodingB, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
super.postConstruct();
|
||||
myDefaultProfileValidationSupport = new DefaultProfileValidationSupport(myFhirContext);
|
||||
myValidationSupport = new CachingValidationSupport(new ValidationSupportChain(myDefaultProfileValidationSupport, myJpaValidationSupport));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeCaches() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequest) {
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl, IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theDisplay, CodingDt theCoding, CodeableConceptDt theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
throw new UnsupportedOperationException(Msg.code(951));
|
||||
}
|
||||
|
||||
public static String toStringOrNull(IPrimitiveType<String> thePrimitive) {
|
||||
return thePrimitive != null ? thePrimitive.getValue() : null;
|
||||
}
|
||||
|
||||
}
|
|
@ -63,7 +63,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
|||
|
||||
@Override
|
||||
public IBaseBundle processMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||
return JpaResourceDao.throwProcessMessageNotImplemented();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
|
@ -36,7 +35,6 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
|||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.param.UriParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -52,12 +50,11 @@ import org.hl7.fhir.r4.model.ValueSet;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
@ -89,8 +86,11 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
|
|||
private Class<? extends IBaseResource> myCodeSystemType;
|
||||
private Class<? extends IBaseResource> myStructureDefinitionType;
|
||||
private Class<? extends IBaseResource> myValueSetType;
|
||||
private Class<? extends IBaseResource> myQuestionnaireType;
|
||||
private Class<? extends IBaseResource> myImplementationGuideType;
|
||||
|
||||
// TODO: JA2 We shouldn't need to cache here, but we probably still should since the
|
||||
// TermReadSvcImpl calls these methods as a part of its "isCodeSystemSupported" calls.
|
||||
// We should modify CachingValidationSupport to cache the results of "isXXXSupported"
|
||||
// at which point we could do away with this cache
|
||||
private Cache<String, IBaseResource> myLoadCache = Caffeine.newBuilder().maximumSize(1000).expireAfterWrite(1, TimeUnit.MINUTES).build();
|
||||
|
||||
/**
|
||||
|
@ -109,7 +109,7 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
|
|||
public IBaseResource fetchCodeSystem(String theSystem) {
|
||||
if (TermReadSvcUtil.isLoincUnversionedCodeSystem(theSystem)) {
|
||||
Optional<IBaseResource> currentCSOpt = getCodeSystemCurrentVersion(new UriType(theSystem));
|
||||
if (! currentCSOpt.isPresent()) {
|
||||
if (!currentCSOpt.isPresent()) {
|
||||
ourLog.info("Couldn't find current version of CodeSystem: " + theSystem);
|
||||
}
|
||||
return currentCSOpt.orElse(null);
|
||||
|
@ -123,7 +123,7 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
|
|||
* version is always pointed by the ForcedId for the no-versioned CS
|
||||
*/
|
||||
private Optional<IBaseResource> getCodeSystemCurrentVersion(UriType theUrl) {
|
||||
if (! theUrl.getValueAsString().contains(LOINC_LOW)) return Optional.empty();
|
||||
if (!theUrl.getValueAsString().contains(LOINC_LOW)) return Optional.empty();
|
||||
|
||||
return myTermReadSvc.readCodeSystemByForcedId(LOINC_LOW);
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
|
|||
*/
|
||||
private Optional<IBaseResource> getValueSetCurrentVersion(UriType theUrl) {
|
||||
Optional<String> vsIdOpt = TermReadSvcUtil.getValueSetId(theUrl.getValueAsString());
|
||||
if (! vsIdOpt.isPresent()) return Optional.empty();
|
||||
if (!vsIdOpt.isPresent()) return Optional.empty();
|
||||
|
||||
IFhirResourceDao<? extends IBaseResource> valueSetResourceDao = myDaoRegistry.getResourceDao(myValueSetType);
|
||||
IBaseResource valueSet = valueSetResourceDao.read(new IdDt("ValueSet", vsIdOpt.get()));
|
||||
|
@ -188,17 +188,8 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
|
|||
|
||||
private <T extends IBaseResource> IBaseResource doFetchResource(@Nullable Class<T> theClass, String theUri) {
|
||||
if (theClass == null) {
|
||||
Supplier<IBaseResource>[] fetchers = new Supplier[]{
|
||||
() -> doFetchResource(ValueSet.class, theUri),
|
||||
() -> doFetchResource(CodeSystem.class, theUri),
|
||||
() -> doFetchResource(StructureDefinition.class, theUri)
|
||||
};
|
||||
return Arrays
|
||||
.stream(fetchers)
|
||||
.map(t -> t.get())
|
||||
.filter(t -> t != myNoMatch)
|
||||
.findFirst()
|
||||
.orElse(myNoMatch);
|
||||
Supplier<IBaseResource>[] fetchers = new Supplier[]{() -> doFetchResource(ValueSet.class, theUri), () -> doFetchResource(CodeSystem.class, theUri), () -> doFetchResource(StructureDefinition.class, theUri)};
|
||||
return Arrays.stream(fetchers).map(t -> t.get()).filter(t -> t != myNoMatch).findFirst().orElse(myNoMatch);
|
||||
}
|
||||
|
||||
IdType id = new IdType(theUri);
|
||||
|
@ -234,6 +225,20 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
|
|||
}
|
||||
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));
|
||||
search = myDaoRegistry.getResourceDao(resourceName).search(params);
|
||||
|
||||
if (search.isEmpty() && myFhirContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
|
||||
params = new SearchParameterMap();
|
||||
params.setLoadSynchronousUpTo(1);
|
||||
if (versionSeparator != -1) {
|
||||
params.add(ValueSet.SP_VERSION, new TokenParam(theUri.substring(versionSeparator + 1)));
|
||||
params.add("system", new UriParam(theUri.substring(0, versionSeparator)));
|
||||
} else {
|
||||
params.add("system", new UriParam(theUri));
|
||||
}
|
||||
params.setSort(new SortSpec("_lastUpdated").setOrder(SortOrderEnum.DESC));
|
||||
search = myDaoRegistry.getResourceDao(resourceName).search(params);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case "StructureDefinition": {
|
||||
|
@ -312,8 +317,6 @@ public class JpaPersistedResourceValidationSupport implements IValidationSupport
|
|||
public void start() {
|
||||
myStructureDefinitionType = myFhirContext.getResourceDefinition("StructureDefinition").getImplementingClass();
|
||||
myValueSetType = myFhirContext.getResourceDefinition("ValueSet").getImplementingClass();
|
||||
myQuestionnaireType = myFhirContext.getResourceDefinition("Questionnaire").getImplementingClass();
|
||||
myImplementationGuideType = myFhirContext.getResourceDefinition("ImplementationGuide").getImplementingClass();
|
||||
|
||||
if (myFhirContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2)) {
|
||||
myCodeSystemType = myFhirContext.getResourceDefinition("CodeSystem").getImplementingClass();
|
||||
|
|
|
@ -20,6 +20,9 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
/**
|
||||
|
@ -28,6 +31,15 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
*/
|
||||
public class JpaResourceDao<T extends IBaseResource> extends BaseHapiFhirResourceDao<T> {
|
||||
|
||||
// nothing yet
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public JpaResourceDao() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public static IBaseBundle throwProcessMessageNotImplemented() {
|
||||
throw new NotImplementedOperationException(Msg.code(945) + "This operation is not yet implemented on this server");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.util.DatatypeUtil.toStringValue;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class JpaResourceDaoCodeSystem<T extends IBaseResource> extends BaseHapiFhirResourceDao<T> implements IFhirResourceDaoCodeSystem<T> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JpaResourceDaoCodeSystem.class);
|
||||
@Autowired
|
||||
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
|
||||
@Autowired
|
||||
protected IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
protected ITermDeferredStorageSvc myTermDeferredStorageSvc;
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
private FhirTerser myTerser;
|
||||
@Autowired
|
||||
private VersionCanonicalizer myVersionCanonicalizer;
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
super.start();
|
||||
myTerser = myFhirContext.newTerser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
|
||||
List<IIdType> valueSetIds;
|
||||
List<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(org.hl7.fhir.r4.model.CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
|
||||
valueSetIds = new ArrayList<>();
|
||||
for (ResourcePersistentId next : ids) {
|
||||
IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
|
||||
valueSetIds.add(id);
|
||||
}
|
||||
return valueSetIds;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IBaseCoding theCoding, RequestDetails theRequestDetails) {
|
||||
return lookupCode(theCode, theSystem, theCoding, null, theRequestDetails);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IBaseCoding theCoding, IPrimitiveType<String> theDisplayLanguage, RequestDetails theRequestDetails) {
|
||||
return doLookupCode(myFhirContext, myTerser, myValidationSupport, theCode, theSystem, theCoding, theDisplayLanguage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, IBaseCoding theCodingA, IBaseCoding theCodingB, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(T theResourceToDelete, ResourceTable theEntityToDelete, RequestDetails theRequestDetails) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete, theRequestDetails);
|
||||
|
||||
myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
|
||||
org.hl7.fhir.r4.model.CodeSystem cs = myVersionCanonicalizer.codeSystemToCanonical(theResource);
|
||||
addPidToResource(theEntity, cs);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, (ResourceTable) theEntity, theRequest);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl, IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode, IPrimitiveType<String> theDisplay, IBaseCoding theCoding, IBaseDatatype theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
CodeableConcept codeableConcept = myVersionCanonicalizer.codeableConceptToCanonical(theCodeableConcept);
|
||||
boolean haveCodeableConcept = codeableConcept != null && codeableConcept.getCoding().size() > 0;
|
||||
|
||||
Coding coding = myVersionCanonicalizer.codingToCanonical(theCoding);
|
||||
boolean haveCoding = coding != null && !coding.isEmpty();
|
||||
|
||||
String code = toStringValue(theCode);
|
||||
boolean haveCode = isNotBlank(code);
|
||||
|
||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
||||
throw new InvalidRequestException(Msg.code(906) + "No code, coding, or codeableConcept provided to validate.");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(907) + "$validate-code can only validate (code) OR (coding) OR (codeableConcept)");
|
||||
}
|
||||
|
||||
String codeSystemUrl;
|
||||
if (theCodeSystemId != null) {
|
||||
IBaseResource codeSystem = read(theCodeSystemId, theRequestDetails);
|
||||
codeSystemUrl = CommonCodeSystemsTerminologyService.getCodeSystemUrl(codeSystem);
|
||||
} else if (isNotBlank(toStringValue(theCodeSystemUrl))) {
|
||||
codeSystemUrl = toStringValue(theCodeSystemUrl);
|
||||
} else {
|
||||
throw new InvalidRequestException(Msg.code(908) + "Either CodeSystem ID or CodeSystem identifier must be provided. Unable to validate.");
|
||||
}
|
||||
|
||||
if (haveCodeableConcept) {
|
||||
CodeValidationResult anyValidation = null;
|
||||
for (int i = 0; i < codeableConcept.getCoding().size(); i++) {
|
||||
Coding nextCoding = codeableConcept.getCoding().get(i);
|
||||
if (nextCoding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(nextCoding.getSystem())) {
|
||||
throw new InvalidRequestException(Msg.code(909) + "Coding.system '" + nextCoding.getSystem() + "' does not equal with CodeSystem.url '" + codeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = nextCoding.getSystem();
|
||||
}
|
||||
code = nextCoding.getCode();
|
||||
String display = nextCoding.getDisplay();
|
||||
CodeValidationResult nextValidation = codeSystemValidateCode(codeSystemUrl, toStringValue(theVersion), code, display);
|
||||
anyValidation = nextValidation;
|
||||
if (nextValidation.isOk()) {
|
||||
return nextValidation;
|
||||
}
|
||||
}
|
||||
return anyValidation;
|
||||
} else if (haveCoding) {
|
||||
if (coding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(coding.getSystem())) {
|
||||
throw new InvalidRequestException(Msg.code(910) + "Coding.system '" + coding.getSystem() + "' does not equal with CodeSystem.url '" + codeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = coding.getSystem();
|
||||
}
|
||||
code = coding.getCode();
|
||||
String display = coding.getDisplay();
|
||||
return codeSystemValidateCode(codeSystemUrl, toStringValue(theVersion), code, display);
|
||||
} else {
|
||||
String display = toStringValue(theDisplay);
|
||||
return codeSystemValidateCode(codeSystemUrl, toStringValue(theVersion), code, display);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private CodeValidationResult codeSystemValidateCode(String theCodeSystemUrl, String theVersion, String theCode, String theDisplay) {
|
||||
ValidationSupportContext context = new ValidationSupportContext(myValidationSupport);
|
||||
ConceptValidationOptions options = new ConceptValidationOptions();
|
||||
options.setValidateDisplay(isNotBlank(theDisplay));
|
||||
|
||||
String codeSystemUrl = createVersionedSystemIfVersionIsPresent(theCodeSystemUrl, theVersion);
|
||||
|
||||
CodeValidationResult retVal = myValidationSupport.validateCode(context, options, codeSystemUrl, theCode, theDisplay, null);
|
||||
if (retVal == null) {
|
||||
retVal = new CodeValidationResult();
|
||||
retVal.setMessage("Terminology service was unable to provide validation for " + codeSystemUrl + "#" + theCode);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static IValidationSupport.LookupCodeResult doLookupCode(FhirContext theFhirContext, FhirTerser theFhirTerser, IValidationSupport theValidationSupport, IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, IBaseCoding theCoding, IPrimitiveType<String> theDisplayLanguage) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(extractCodingSystem(theCoding)) && isNotBlank(extractCodingCode(theCoding));
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
boolean haveDisplayLanguage = theDisplayLanguage != null && theDisplayLanguage.isEmpty() == false;
|
||||
|
||||
if (!haveCoding && !(haveSystem && haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1126) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1127) + "$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
|
||||
}
|
||||
|
||||
String code;
|
||||
String system;
|
||||
if (haveCoding) {
|
||||
code = extractCodingCode(theCoding);
|
||||
system = extractCodingSystem(theCoding);
|
||||
String version = extractCodingVersion(theFhirContext, theFhirTerser, theCoding);
|
||||
if (isNotBlank(version)) {
|
||||
system = system + "|" + version;
|
||||
}
|
||||
} else {
|
||||
code = theCode.getValue();
|
||||
system = theSystem.getValue();
|
||||
}
|
||||
|
||||
String displayLanguage = null;
|
||||
if (haveDisplayLanguage) {
|
||||
displayLanguage = theDisplayLanguage.getValue();
|
||||
}
|
||||
|
||||
ourLog.info("Looking up {} / {}", system, code);
|
||||
|
||||
if (theValidationSupport.isCodeSystemSupported(new ValidationSupportContext(theValidationSupport), system)) {
|
||||
|
||||
ourLog.info("Code system {} is supported", system);
|
||||
IValidationSupport.LookupCodeResult retVal = theValidationSupport.lookupCode(new ValidationSupportContext(theValidationSupport), system, code, displayLanguage);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We didn't find it..
|
||||
return IValidationSupport.LookupCodeResult.notFound(system, code);
|
||||
}
|
||||
|
||||
private static String extractCodingSystem(IBaseCoding theCoding) {
|
||||
return theCoding.getSystem();
|
||||
}
|
||||
|
||||
private static String extractCodingCode(IBaseCoding theCoding) {
|
||||
return theCoding.getCode();
|
||||
}
|
||||
|
||||
private static String extractCodingVersion(FhirContext theFhirContext, FhirTerser theFhirTerser, IBaseCoding theCoding) {
|
||||
if (theFhirContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
|
||||
return null;
|
||||
}
|
||||
return theFhirTerser.getSinglePrimitiveValueOrNull(theCoding, "version");
|
||||
}
|
||||
|
||||
public static String createVersionedSystemIfVersionIsPresent(String theCodeSystemUrl, String theVersion) {
|
||||
String codeSystemUrl = theCodeSystemUrl;
|
||||
if (isNotBlank(theVersion)) {
|
||||
codeSystemUrl = codeSystemUrl + "|" + theVersion;
|
||||
}
|
||||
return codeSystemUrl;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
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.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.search.autocomplete.ValueSetAutocompleteOptions;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.JpaResourceDaoCodeSystem.createVersionedSystemIfVersionIsPresent;
|
||||
import static ca.uhn.fhir.jpa.provider.ValueSetOperationProvider.createValueSetExpansionOptions;
|
||||
import static ca.uhn.fhir.util.DatatypeUtil.toStringValue;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class JpaResourceDaoValueSet<T extends IBaseResource> extends BaseHapiFhirResourceDao<T> implements IFhirResourceDaoValueSet<T> {
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private VersionCanonicalizer myVersionCanonicalizer;
|
||||
@Autowired(required = false)
|
||||
private IFulltextSearchSvc myFulltextSearch;
|
||||
|
||||
@Override
|
||||
public T expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) {
|
||||
T source = read(theId, theRequestDetails);
|
||||
return expand(source, theOptions);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) {
|
||||
IValidationSupport.ValueSetExpansionOutcome expansionOutcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), theOptions, theUri);
|
||||
return extractValueSetOrThrowException(expansionOutcome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T expand(T theSource, ValueSetExpansionOptions theOptions) {
|
||||
IValidationSupport.ValueSetExpansionOutcome expansionOutcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), theOptions, theSource);
|
||||
return extractValueSetOrThrowException(expansionOutcome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T expand(IIdType theId, T theValueSet, IPrimitiveType<String> theUrl, IPrimitiveType<String> theValueSetVersion, IPrimitiveType<String> theFilter, IPrimitiveType<String> theContext, IPrimitiveType<String> theContextDirection, IPrimitiveType<Integer> theOffset, IPrimitiveType<Integer> theCount, IPrimitiveType<String> theDisplayLanguage, IPrimitiveType<Boolean> theIncludeHierarchy, RequestDetails theRequestDetails) {
|
||||
boolean haveId = theId != null && theId.hasIdPart();
|
||||
boolean haveIdentifier = theUrl != null && isNotBlank(theUrl.getValue());
|
||||
boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty();
|
||||
boolean haveValueSetVersion = theValueSetVersion != null && !theValueSetVersion.isEmpty();
|
||||
boolean haveContextDirection = theContextDirection != null && !theContextDirection.isEmpty();
|
||||
boolean haveContext = theContext != null && !theContext.isEmpty();
|
||||
|
||||
boolean isAutocompleteExtension = haveContext && haveContextDirection && "existing".equals(theContextDirection.getValue());
|
||||
|
||||
if (isAutocompleteExtension) {
|
||||
// this is a funky extension for NIH. Do our own thing and return.
|
||||
ValueSetAutocompleteOptions options = ValueSetAutocompleteOptions.validateAndParseOptions(myDaoConfig, theContext, theFilter, theCount, theId, theUrl, theValueSet);
|
||||
if (myFulltextSearch == null || myFulltextSearch.isDisabled()) {
|
||||
throw new InvalidRequestException(Msg.code(2083) + " Autocomplete is not supported on this server, as the fulltext search service is not configured.");
|
||||
} else {
|
||||
return (T) myFulltextSearch.tokenAutocompleteValueSetSearch(options);
|
||||
}
|
||||
}
|
||||
|
||||
if (!haveId && !haveIdentifier && !haveValueSet) {
|
||||
if (myFhirContext.getVersion().getVersion() == FhirVersionEnum.DSTU2) {
|
||||
// "url" parameter is called "identifier" in DSTU2
|
||||
throw new InvalidRequestException(Msg.code(1130) + "$expand operation at the type level (no ID specified) requires an identifier or a valueSet as a part of the request");
|
||||
}
|
||||
throw new InvalidRequestException(Msg.code(1133) + "$expand operation at the type level (no ID specified) requires a url or a valueSet as a part of the request.");
|
||||
}
|
||||
|
||||
if (!LogicUtil.multiXor(haveId, haveIdentifier, haveValueSet)) {
|
||||
if (myFhirContext.getVersion().getVersion() == FhirVersionEnum.DSTU2) {
|
||||
// "url" parameter is called "identifier" in DSTU2
|
||||
throw new InvalidRequestException(Msg.code(1131) + "$expand must EITHER be invoked at the type level, or have an identifier specified, or have a ValueSet specified. Can not combine these options.");
|
||||
}
|
||||
throw new InvalidRequestException(Msg.code(1134) + "$expand must EITHER be invoked at the instance level, or have a url specified, or have a ValueSet specified. Can not combine these options.");
|
||||
}
|
||||
|
||||
ValueSetExpansionOptions options = createValueSetExpansionOptions(myDaoConfig, theOffset, theCount, theIncludeHierarchy, theFilter, theDisplayLanguage);
|
||||
|
||||
IValidationSupport.ValueSetExpansionOutcome outcome;
|
||||
if (haveId) {
|
||||
IBaseResource valueSet = read(theId, theRequestDetails);
|
||||
outcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, valueSet);
|
||||
} else if (haveIdentifier) {
|
||||
String url;
|
||||
if (haveValueSetVersion) {
|
||||
url = theUrl.getValue() + "|" + theValueSetVersion.getValue();
|
||||
} else {
|
||||
url = theUrl.getValue();
|
||||
}
|
||||
outcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, url);
|
||||
} else {
|
||||
outcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, theValueSet);
|
||||
}
|
||||
|
||||
return extractValueSetOrThrowException(outcome);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T extractValueSetOrThrowException(IValidationSupport.ValueSetExpansionOutcome outcome) {
|
||||
if (outcome == null) {
|
||||
throw new InternalErrorException(Msg.code(2028) + "No validation support module was able to expand the given valueset");
|
||||
}
|
||||
|
||||
if (outcome.getError() != null) {
|
||||
throw new PreconditionFailedException(Msg.code(2029) + outcome.getError());
|
||||
}
|
||||
|
||||
return (T) outcome.getValueSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theValueSetId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, IBaseCoding theCoding,
|
||||
IBaseDatatype theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
CodeableConcept codeableConcept = myVersionCanonicalizer.codeableConceptToCanonical(theCodeableConcept);
|
||||
boolean haveCodeableConcept = codeableConcept != null && codeableConcept.getCoding().size() > 0;
|
||||
|
||||
Coding canonicalCodingToValidate = myVersionCanonicalizer.codingToCanonical((IBaseCoding) theCoding);
|
||||
boolean haveCoding = canonicalCodingToValidate != null && !canonicalCodingToValidate.isEmpty();
|
||||
|
||||
boolean haveCode = theCode != null && !theCode.isEmpty();
|
||||
|
||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
||||
throw new InvalidRequestException(Msg.code(899) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(900) + "$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
||||
}
|
||||
|
||||
String valueSetIdentifier;
|
||||
if (theValueSetId != null) {
|
||||
IBaseResource valueSet = read(theValueSetId, theRequestDetails);
|
||||
StringBuilder valueSetIdentifierBuilder = new StringBuilder(CommonCodeSystemsTerminologyService.getValueSetUrl(valueSet));
|
||||
String valueSetVersion = CommonCodeSystemsTerminologyService.getValueSetVersion(valueSet);
|
||||
if (valueSetVersion != null) {
|
||||
valueSetIdentifierBuilder.append("|").append(valueSetVersion);
|
||||
}
|
||||
valueSetIdentifier = valueSetIdentifierBuilder.toString();
|
||||
} else if (isNotBlank(toStringValue(theValueSetIdentifier))) {
|
||||
valueSetIdentifier = toStringValue(theValueSetIdentifier);
|
||||
} else {
|
||||
throw new InvalidRequestException(Msg.code(901) + "Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
||||
}
|
||||
|
||||
if (haveCodeableConcept) {
|
||||
IValidationSupport.CodeValidationResult anyValidation = null;
|
||||
for (int i = 0; i < codeableConcept.getCoding().size(); i++) {
|
||||
Coding nextCoding = codeableConcept.getCoding().get(i);
|
||||
String system = createVersionedSystemIfVersionIsPresent(nextCoding.getSystem(), nextCoding.getVersion());
|
||||
String code = nextCoding.getCode();
|
||||
String display = nextCoding.getDisplay();
|
||||
|
||||
IValidationSupport.CodeValidationResult nextValidation = validateCode(system, code, display, valueSetIdentifier);
|
||||
anyValidation = nextValidation;
|
||||
if (nextValidation.isOk()) {
|
||||
return nextValidation;
|
||||
}
|
||||
}
|
||||
return anyValidation;
|
||||
} else if (haveCoding) {
|
||||
String system = createVersionedSystemIfVersionIsPresent(canonicalCodingToValidate.getSystem(), canonicalCodingToValidate.getVersion());
|
||||
String code = canonicalCodingToValidate.getCode();
|
||||
String display = canonicalCodingToValidate.getDisplay();
|
||||
return validateCode(system, code, display, valueSetIdentifier);
|
||||
} else {
|
||||
String system = toStringValue(theSystem);
|
||||
String code = toStringValue(theCode);
|
||||
String display = toStringValue(theDisplay);
|
||||
return validateCode(system, code, display, valueSetIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
private IValidationSupport.CodeValidationResult validateCode(String theSystem, String theCode, String theDisplay, String theValueSetIdentifier) {
|
||||
ValidationSupportContext context = new ValidationSupportContext(myValidationSupport);
|
||||
ConceptValidationOptions options = new ConceptValidationOptions();
|
||||
options.setValidateDisplay(isNotBlank(theDisplay));
|
||||
IValidationSupport.CodeValidationResult result = myValidationSupport.validateCode(context, options, theSystem, theCode, theDisplay, theValueSetIdentifier);
|
||||
|
||||
if (result == null) {
|
||||
result = new IValidationSupport.CodeValidationResult();
|
||||
result.setMessage("Validator is unable to provide validation for " + theCode + "#" + theSystem + " - Unknown or unusable ValueSet[" + theValueSetIdentifier + "]");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (getConfig().isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
ValueSet valueSet = myVersionCanonicalizer.valueSetToCanonical(theResource);
|
||||
myTerminologySvc.storeTermValueSet(retVal, valueSet);
|
||||
} else {
|
||||
myTerminologySvc.deleteValueSetAndChildren(retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -47,11 +47,11 @@ public interface ITermConceptDao extends JpaRepository<TermConcept, Long>, IHapi
|
|||
@Query("SELECT COUNT(t) FROM TermConcept t WHERE t.myCodeSystem.myId = :cs_pid")
|
||||
Integer countByCodeSystemVersion(@Param("cs_pid") Long thePid);
|
||||
|
||||
@Query("SELECT c FROM TermConcept c WHERE c.myCodeSystem = :code_system AND c.myCode = :code")
|
||||
Optional<TermConcept> findByCodeSystemAndCode(@Param("code_system") TermCodeSystemVersion theCodeSystem, @Param("code") String theCode);
|
||||
@Query("SELECT c FROM TermConcept c WHERE c.myCodeSystemVersionPid = :csv_pid AND c.myCode = :code")
|
||||
Optional<TermConcept> findByCodeSystemAndCode(@Param("csv_pid") Long theCodeSystemVersionPid, @Param("code") String theCode);
|
||||
|
||||
@Query("FROM TermConcept WHERE myCodeSystem = :code_system AND myCode in (:codeList)")
|
||||
List<TermConcept> findByCodeSystemAndCodeList(@Param("code_system") TermCodeSystemVersion theCodeSystem, @Param("codeList") List<String> theCodeList);
|
||||
@Query("FROM TermConcept WHERE myCodeSystemVersionPid = :csv_pid AND myCode in (:codeList)")
|
||||
List<TermConcept> findByCodeSystemAndCodeList(@Param("csv_pid") Long theCodeSystem, @Param("codeList") List<String> theCodeList);
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM TermConcept WHERE myCodeSystem.myId = :cs_pid")
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_40;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40;
|
||||
import org.hl7.fhir.dstu3.model.CodeSystem;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
@Transactional
|
||||
public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemDstu3.class);
|
||||
@Autowired
|
||||
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
|
||||
@Autowired
|
||||
protected ITermDeferredStorageSvc myTermDeferredStorageSvc;
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
public FhirResourceDaoCodeSystemDstu3() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
|
||||
List<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
|
||||
List<IIdType> valueSetIds = new ArrayList<>();
|
||||
for (ResourcePersistentId next : ids) {
|
||||
IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
|
||||
valueSetIds.add(id);
|
||||
}
|
||||
return valueSetIds;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
return lookupCode(theCode, theSystem, theCoding, null, theRequestDetails);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, IPrimitiveType<String> theDisplayLanguage, RequestDetails theRequestDetails) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
boolean haveDisplayLanguage = theDisplayLanguage != null && theDisplayLanguage.isEmpty() == false;
|
||||
|
||||
if (!haveCoding && !(haveSystem && haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1075) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1076) + "$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
|
||||
}
|
||||
|
||||
String code;
|
||||
String system;
|
||||
if (haveCoding) {
|
||||
code = theCoding.getCode();
|
||||
if (theCoding.hasVersion()) {
|
||||
system = theCoding.getSystem() + "|" + theCoding.getVersion();
|
||||
} else {
|
||||
system = theCoding.getSystem();
|
||||
}
|
||||
} else {
|
||||
code = theCode.getValue();
|
||||
system = theSystem.getValue();
|
||||
}
|
||||
|
||||
String displayLanguage = null;
|
||||
if (haveDisplayLanguage) {
|
||||
displayLanguage = theDisplayLanguage.getValue();
|
||||
}
|
||||
|
||||
ourLog.debug("Looking up {} / {}", system, code);
|
||||
|
||||
if (myValidationSupport.isCodeSystemSupported(new ValidationSupportContext(myValidationSupport), system)) {
|
||||
ourLog.debug("Code system {} is supported", system);
|
||||
IValidationSupport.LookupCodeResult result = myValidationSupport.lookupCode(new ValidationSupportContext(myValidationSupport), system, code, displayLanguage);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find it..
|
||||
return IValidationSupport.LookupCodeResult.notFound(system, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete, RequestDetails theRequestDetails) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete, theRequestDetails);
|
||||
|
||||
myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
|
||||
CodeSystem csDstu3 = (CodeSystem) theResource;
|
||||
|
||||
org.hl7.fhir.r4.model.CodeSystem cs = (org.hl7.fhir.r4.model.CodeSystem) VersionConvertorFactory_30_40.convertResource(csDstu3, new BaseAdvisor_30_40(false));
|
||||
addPidToResource(theEntity, cs);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, (ResourceTable) theEntity);
|
||||
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl, IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theDisplay, Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.codeSystemValidateCode(theCodeSystemId, toStringOrNull(theCodeSystemUrl), toStringOrNull(theVersion), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoMessageHeader;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import org.hl7.fhir.dstu3.model.MessageHeader;
|
||||
|
||||
public class FhirResourceDaoMessageHeaderDstu3 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||
// nothing right now
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_40;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
|
||||
public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||
|
||||
@Override
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) {
|
||||
org.hl7.fhir.dstu3.model.ValueSet source = read(theId, theRequestDetails);
|
||||
return expand(source, theOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expand(org.hl7.fhir.dstu3.model.ValueSet theSource, ValueSetExpansionOptions theOptions) {
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalInput = (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_30_40.convertResource(theSource, new BaseAdvisor_30_40(false));
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, canonicalInput);
|
||||
return (ValueSet) VersionConvertorFactory_30_40.convertResource(canonicalOutput, new BaseAdvisor_30_40(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.hl7.fhir.dstu3.model.ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) {
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, theUri);
|
||||
return (ValueSet) VersionConvertorFactory_30_40.convertResource(canonicalOutput, new BaseAdvisor_30_40(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeCaches() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (getConfig().isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
try {
|
||||
ValueSet valueSet = (ValueSet) theResource;
|
||||
org.hl7.fhir.r4.model.ValueSet converted = (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_30_40.convertResource(valueSet, new BaseAdvisor_30_40(false));
|
||||
myTerminologySvc.storeTermValueSet(retVal, converted);
|
||||
} catch (FHIRException fe) {
|
||||
throw new InternalErrorException(Msg.code(1080) + fe);
|
||||
}
|
||||
} else {
|
||||
myTerminologySvc.deleteValueSetAndChildren(retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static ConceptValidationOptions vsValidateCodeOptions() {
|
||||
return new ConceptValidationOptions().setValidateDisplay(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -21,9 +21,8 @@ package ca.uhn.fhir.jpa.dao.dstu3;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||
import ca.uhn.fhir.jpa.dao.JpaResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Meta;
|
||||
|
@ -71,7 +70,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
@Override
|
||||
public IBaseBundle processMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||
return JpaResourceDao.throwProcessMessageNotImplemented();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.hl7.fhir.common.hapi.validation.support.ValidationConstants.LOINC_LOW;
|
||||
|
||||
public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR4.class);
|
||||
@Autowired
|
||||
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
|
||||
@Autowired
|
||||
protected ITermDeferredStorageSvc myTermDeferredStorageSvc;
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
@Override
|
||||
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
|
||||
List<IIdType> valueSetIds;
|
||||
List<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
|
||||
valueSetIds = new ArrayList<>();
|
||||
for (ResourcePersistentId next : ids) {
|
||||
IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
|
||||
valueSetIds.add(id);
|
||||
}
|
||||
return valueSetIds;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
return lookupCode(theCode, theSystem, theCoding, null, theRequestDetails);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, IPrimitiveType<String> theDisplayLanguage, RequestDetails theRequestDetails) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
boolean haveDisplayLanguage = theDisplayLanguage != null && theDisplayLanguage.isEmpty() == false;
|
||||
|
||||
if (!haveCoding && !(haveSystem && haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1108) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1109) + "$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
|
||||
}
|
||||
|
||||
String code;
|
||||
String system;
|
||||
if (haveCoding) {
|
||||
code = theCoding.getCode();
|
||||
if (theCoding.hasVersion()) {
|
||||
system = theCoding.getSystem() + "|" + theCoding.getVersion();
|
||||
} else {
|
||||
system = theCoding.getSystem();
|
||||
}
|
||||
} else {
|
||||
code = theCode.getValue();
|
||||
system = theSystem.getValue();
|
||||
}
|
||||
|
||||
String displayLanguage = null;
|
||||
if (haveDisplayLanguage) {
|
||||
displayLanguage = theDisplayLanguage.getValue();
|
||||
}
|
||||
|
||||
ourLog.debug("Looking up {} / {}", system, code);
|
||||
|
||||
if (myValidationSupport.isCodeSystemSupported(new ValidationSupportContext(myValidationSupport), system)) {
|
||||
|
||||
ourLog.debug("Code system {} is supported", system);
|
||||
IValidationSupport.LookupCodeResult retVal = myValidationSupport.lookupCode(new ValidationSupportContext(myValidationSupport), system, code, displayLanguage);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We didn't find it..
|
||||
return IValidationSupport.LookupCodeResult.notFound(system, code);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete, RequestDetails theRequestDetails) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete, theRequestDetails);
|
||||
|
||||
myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
CodeSystem cs = (CodeSystem) theResource;
|
||||
addPidToResource(theEntity, theResource);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, (ResourceTable) theEntity, theRequest);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl,
|
||||
IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode, IPrimitiveType<String> theDisplay,
|
||||
Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
return myTerminologySvc.codeSystemValidateCode(theCodeSystemId, toStringOrNull(theCodeSystemUrl), toStringOrNull(theVersion), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DaoMethodOutcome create(CodeSystem theResource, String theIfNoneExist, boolean thePerformIndexing,
|
||||
@Nonnull TransactionDetails theTransactionDetails, RequestDetails theRequestDetails) {
|
||||
// loinc CodeSystem must have an ID
|
||||
if (isNotBlank(theResource.getUrl()) && theResource.getUrl().contains(LOINC_LOW)
|
||||
&& isBlank(theResource.getIdElement().getIdPart())) {
|
||||
throw new InvalidParameterException(Msg.code(1110) + "'loinc' CodeSystem must have an ID");
|
||||
}
|
||||
return myTransactionService.execute(theRequestDetails, theTransactionDetails,
|
||||
tx -> doCreateForPost(theResource, theIfNoneExist, thePerformIndexing, theTransactionDetails, theRequestDetails));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoMessageHeader;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import org.hl7.fhir.r4.model.MessageHeader;
|
||||
|
||||
public class FhirResourceDaoMessageHeaderR4 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||
// nothing right now
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
|
||||
|
||||
public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
return expand(source, theOptions);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) {
|
||||
return myTerminologySvc.expandValueSet(theOptions, theUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, ValueSetExpansionOptions theOptions) {
|
||||
return myTerminologySvc.expandValueSet(theOptions, theSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeCaches() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (getConfig().isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
ValueSet valueSet = (ValueSet) theResource;
|
||||
myTerminologySvc.storeTermValueSet(retVal, valueSet);
|
||||
} else {
|
||||
myTerminologySvc.deleteValueSetAndChildren(retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||
import ca.uhn.fhir.jpa.dao.JpaResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
@ -45,7 +45,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
@Override
|
||||
public IBaseBundle processMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||
return JpaResourceDao.throwProcessMessageNotImplemented();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4b;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_43_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_43_50;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4b.model.CodeSystem;
|
||||
import org.hl7.fhir.r4b.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4b.model.Coding;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class FhirResourceDaoCodeSystemR4B extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR4B.class);
|
||||
@Autowired
|
||||
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
|
||||
@Autowired
|
||||
protected IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
protected ITermDeferredStorageSvc myTermDeferredStorageSvc;
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
@Override
|
||||
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
|
||||
List<IIdType> valueSetIds;
|
||||
List<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(org.hl7.fhir.r4.model.CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
|
||||
valueSetIds = new ArrayList<>();
|
||||
for (ResourcePersistentId next : ids) {
|
||||
IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
|
||||
valueSetIds.add(id);
|
||||
}
|
||||
return valueSetIds;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
return lookupCode(theCode, theSystem, theCoding, null, theRequestDetails);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, IPrimitiveType<String> theDisplayLanguage, RequestDetails theRequestDetails) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
boolean haveDisplayLanguage = theDisplayLanguage != null && theDisplayLanguage.isEmpty() == false;
|
||||
|
||||
if (!haveCoding && !(haveSystem && haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(2148) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(2149) + "$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
|
||||
}
|
||||
|
||||
String code;
|
||||
String system;
|
||||
if (haveCoding) {
|
||||
code = theCoding.getCode();
|
||||
if (theCoding.hasVersion()) {
|
||||
system = theCoding.getSystem() + "|" + theCoding.getVersion();
|
||||
} else {
|
||||
system = theCoding.getSystem();
|
||||
}
|
||||
} else {
|
||||
code = theCode.getValue();
|
||||
system = theSystem.getValue();
|
||||
}
|
||||
|
||||
String displayLanguage = null;
|
||||
if (haveDisplayLanguage) {
|
||||
displayLanguage = theDisplayLanguage.getValue();
|
||||
}
|
||||
|
||||
ourLog.info("Looking up {} / {}", system, code);
|
||||
|
||||
if (myValidationSupport.isCodeSystemSupported(new ValidationSupportContext(myValidationSupport), system)) {
|
||||
|
||||
ourLog.info("Code system {} is supported", system);
|
||||
IValidationSupport.LookupCodeResult retVal = myValidationSupport.lookupCode(new ValidationSupportContext(myValidationSupport), system, code, displayLanguage);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We didn't find it..
|
||||
return IValidationSupport.LookupCodeResult.notFound(system, code);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete, RequestDetails theRequestDetails) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete, theRequestDetails);
|
||||
|
||||
myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
|
||||
CodeSystem csR4b = (CodeSystem) theResource;
|
||||
|
||||
org.hl7.fhir.r5.model.CodeSystem csR5 = (org.hl7.fhir.r5.model.CodeSystem) VersionConvertorFactory_43_50.convertResource(csR4b, new BaseAdvisor_43_50(false));
|
||||
org.hl7.fhir.r4.model.CodeSystem csR4 = (org.hl7.fhir.r4.model.CodeSystem) VersionConvertorFactory_40_50.convertResource(csR5, new BaseAdvisor_40_50(false));
|
||||
addPidToResource(theEntity, csR4);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(csR4, (ResourceTable) theEntity);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl,
|
||||
IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode, IPrimitiveType<String> theDisplay,
|
||||
Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
return myTerminologySvc.codeSystemValidateCode(theCodeSystemId, toStringOrNull(theCodeSystemUrl), toStringOrNull(theVersion), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4b;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoMessageHeader;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import org.hl7.fhir.r4b.model.MessageHeader;
|
||||
|
||||
public class FhirResourceDaoMessageHeaderR4B extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||
// nothing right now
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4b;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_43_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_43_50;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4b.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4b.model.Coding;
|
||||
import org.hl7.fhir.r4b.model.ValueSet;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
|
||||
|
||||
public class FhirResourceDaoValueSetR4B extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
return expand(source, theOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) {
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, theUri);
|
||||
org.hl7.fhir.r5.model.ValueSet valueSetR5 = (org.hl7.fhir.r5.model.ValueSet) VersionConvertorFactory_40_50.convertResource(canonicalOutput, new BaseAdvisor_40_50(false));
|
||||
return (ValueSet) VersionConvertorFactory_43_50.convertResource(valueSetR5, new BaseAdvisor_43_50(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, ValueSetExpansionOptions theOptions) {
|
||||
org.hl7.fhir.r5.model.ValueSet canonicalInputR5 = (org.hl7.fhir.r5.model.ValueSet) VersionConvertorFactory_43_50.convertResource(theSource, new BaseAdvisor_43_50(false));
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalInput = (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_40_50.convertResource(canonicalInputR5, new BaseAdvisor_40_50(false));
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, canonicalInput);
|
||||
org.hl7.fhir.r5.model.ValueSet outputR5 = (org.hl7.fhir.r5.model.ValueSet) VersionConvertorFactory_40_50.convertResource(canonicalOutput, new BaseAdvisor_40_50(false));
|
||||
return (ValueSet) VersionConvertorFactory_43_50.convertResource(outputR5, new BaseAdvisor_43_50(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeCaches() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (getConfig().isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
ValueSet valueSet = (ValueSet) theResource;
|
||||
org.hl7.fhir.r5.model.ValueSet valueSetR5 = (org.hl7.fhir.r5.model.ValueSet) VersionConvertorFactory_43_50.convertResource(valueSet, new BaseAdvisor_43_50(false));
|
||||
org.hl7.fhir.r4.model.ValueSet valueSetR4 = (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_40_50.convertResource(valueSetR5, new BaseAdvisor_40_50(false));
|
||||
myTerminologySvc.storeTermValueSet(retVal, valueSetR4);
|
||||
} else {
|
||||
myTerminologySvc.deleteValueSetAndChildren(retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ package ca.uhn.fhir.jpa.dao.r4b;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||
import ca.uhn.fhir.jpa.dao.JpaResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
@ -47,7 +47,7 @@ public class FhirSystemDaoR4B extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
@Override
|
||||
public IBaseBundle processMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||
return JpaResourceDao.throwProcessMessageNotImplemented();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r5;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport.CodeValidationResult;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSystem> implements IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoCodeSystemR5.class);
|
||||
@Autowired
|
||||
protected ITermCodeSystemStorageSvc myTerminologyCodeSystemStorageSvc;
|
||||
@Autowired
|
||||
protected IIdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
protected ITermDeferredStorageSvc myTermDeferredStorageSvc;
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
@Override
|
||||
public List<IIdType> findCodeSystemIdsContainingSystemAndCode(String theCode, String theSystem, RequestDetails theRequest) {
|
||||
List<IIdType> valueSetIds;
|
||||
List<ResourcePersistentId> ids = searchForIds(new SearchParameterMap(org.hl7.fhir.r4.model.CodeSystem.SP_CODE, new TokenParam(theSystem, theCode)), theRequest);
|
||||
valueSetIds = new ArrayList<>();
|
||||
for (ResourcePersistentId next : ids) {
|
||||
IIdType id = myIdHelperService.translatePidIdToForcedId(myFhirContext, "CodeSystem", next);
|
||||
valueSetIds.add(id);
|
||||
}
|
||||
return valueSetIds;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, RequestDetails theRequestDetails) {
|
||||
return lookupCode(theCode, theSystem, theCoding, null, theRequestDetails);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IValidationSupport.LookupCodeResult lookupCode(IPrimitiveType<String> theCode, IPrimitiveType<String> theSystem, Coding theCoding, IPrimitiveType<String> theDisplayLanguage, RequestDetails theRequestDetails) {
|
||||
boolean haveCoding = theCoding != null && isNotBlank(theCoding.getSystem()) && isNotBlank(theCoding.getCode());
|
||||
boolean haveCode = theCode != null && theCode.isEmpty() == false;
|
||||
boolean haveSystem = theSystem != null && theSystem.isEmpty() == false;
|
||||
boolean haveDisplayLanguage = theDisplayLanguage != null && theDisplayLanguage.isEmpty() == false;
|
||||
|
||||
if (!haveCoding && !(haveSystem && haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1126) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCoding, (haveSystem && haveCode)) || (haveSystem != haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(1127) + "$lookup can only validate (system AND code) OR (coding.system AND coding.code)");
|
||||
}
|
||||
|
||||
String code;
|
||||
String system;
|
||||
if (haveCoding) {
|
||||
code = theCoding.getCode();
|
||||
if (theCoding.hasVersion()) {
|
||||
system = theCoding.getSystem() + "|" + theCoding.getVersion();
|
||||
} else {
|
||||
system = theCoding.getSystem();
|
||||
}
|
||||
} else {
|
||||
code = theCode.getValue();
|
||||
system = theSystem.getValue();
|
||||
}
|
||||
|
||||
String displayLanguage = null;
|
||||
if (haveDisplayLanguage) {
|
||||
displayLanguage = theDisplayLanguage.getValue();
|
||||
}
|
||||
|
||||
ourLog.info("Looking up {} / {}", system, code);
|
||||
|
||||
if (myValidationSupport.isCodeSystemSupported(new ValidationSupportContext(myValidationSupport), system)) {
|
||||
|
||||
ourLog.info("Code system {} is supported", system);
|
||||
IValidationSupport.LookupCodeResult retVal = myValidationSupport.lookupCode(new ValidationSupportContext(myValidationSupport), system, code, displayLanguage);
|
||||
if (retVal != null) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We didn't find it..
|
||||
return IValidationSupport.LookupCodeResult.notFound(system, code);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubsumesResult subsumes(IPrimitiveType<String> theCodeA, IPrimitiveType<String> theCodeB, IPrimitiveType<String> theSystem, Coding theCodingA, Coding theCodingB, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.subsumes(theCodeA, theCodeB, theSystem, theCodingA, theCodingB);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void preDelete(CodeSystem theResourceToDelete, ResourceTable theEntityToDelete, RequestDetails theRequestDetails) {
|
||||
super.preDelete(theResourceToDelete, theEntityToDelete, theRequestDetails);
|
||||
|
||||
myTermDeferredStorageSvc.deleteCodeSystemForResource(theEntityToDelete);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
|
||||
CodeSystem csR5 = (CodeSystem) theResource;
|
||||
|
||||
org.hl7.fhir.r4.model.CodeSystem cs = (org.hl7.fhir.r4.model.CodeSystem) VersionConvertorFactory_40_50.convertResource(csR5, new BaseAdvisor_40_50(false));
|
||||
addPidToResource(theEntity, cs);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, (ResourceTable) theEntity);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeValidationResult validateCode(IIdType theCodeSystemId, IPrimitiveType<String> theCodeSystemUrl,
|
||||
IPrimitiveType<String> theVersion, IPrimitiveType<String> theCode, IPrimitiveType<String> theDisplay,
|
||||
Coding theCoding, CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
|
||||
return myTerminologySvc.codeSystemValidateCode(theCodeSystemId, toStringOrNull(theCodeSystemUrl), toStringOrNull(theVersion), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r5;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoMessageHeader;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import org.hl7.fhir.r5.model.MessageHeader;
|
||||
|
||||
public class FhirResourceDaoMessageHeaderR5 extends BaseHapiFhirResourceDao<MessageHeader> implements IFhirResourceDaoMessageHeader<MessageHeader> {
|
||||
// nothing right now
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.dao.r5;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static ca.uhn.fhir.jpa.dao.FhirResourceDaoValueSetDstu2.toStringOrNull;
|
||||
import static ca.uhn.fhir.jpa.dao.dstu3.FhirResourceDaoValueSetDstu3.vsValidateCodeOptions;
|
||||
|
||||
public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet> implements IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> {
|
||||
|
||||
@Override
|
||||
public ValueSet expand(IIdType theId, ValueSetExpansionOptions theOptions, RequestDetails theRequestDetails) {
|
||||
ValueSet source = read(theId, theRequestDetails);
|
||||
return expand(source, theOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expandByIdentifier(String theUri, ValueSetExpansionOptions theOptions) {
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, theUri);
|
||||
return (ValueSet) VersionConvertorFactory_40_50.convertResource(canonicalOutput, new BaseAdvisor_40_50(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSet expand(ValueSet theSource, ValueSetExpansionOptions theOptions) {
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalInput = (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_40_50.convertResource(theSource, new BaseAdvisor_40_50(false));
|
||||
org.hl7.fhir.r4.model.ValueSet canonicalOutput = myTerminologySvc.expandValueSet(theOptions, canonicalInput);
|
||||
return (ValueSet) VersionConvertorFactory_40_50.convertResource(canonicalOutput, new BaseAdvisor_40_50(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IValidationSupport.CodeValidationResult validateCode(IPrimitiveType<String> theValueSetIdentifier, IIdType theId, IPrimitiveType<String> theCode,
|
||||
IPrimitiveType<String> theSystem, IPrimitiveType<String> theDisplay, Coding theCoding,
|
||||
CodeableConcept theCodeableConcept, RequestDetails theRequestDetails) {
|
||||
return myTerminologySvc.validateCode(vsValidateCodeOptions(), theId, toStringOrNull(theValueSetIdentifier), toStringOrNull(theSystem), toStringOrNull(theCode), toStringOrNull(theDisplay), theCoding, theCodeableConcept);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeCaches() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, IBasePersistedResource theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, TransactionDetails theTransactionDetails, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theTransactionDetails, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (getConfig().isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
ValueSet valueSet = (ValueSet) theResource;
|
||||
myTerminologySvc.storeTermValueSet(retVal, (org.hl7.fhir.r4.model.ValueSet) VersionConvertorFactory_40_50.convertResource(valueSet, new BaseAdvisor_40_50(false)));
|
||||
} else {
|
||||
myTerminologySvc.deleteValueSetAndChildren(retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@ package ca.uhn.fhir.jpa.dao.r5;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.dao.FhirResourceDaoMessageHeaderDstu2;
|
||||
import ca.uhn.fhir.jpa.dao.JpaResourceDao;
|
||||
import ca.uhn.fhir.jpa.model.entity.TagDefinition;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
@ -47,7 +47,7 @@ public class FhirSystemDaoR5 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||
|
||||
@Override
|
||||
public IBaseBundle processMessage(RequestDetails theRequestDetails, IBaseBundle theMessage) {
|
||||
return FhirResourceDaoMessageHeaderDstu2.throwProcessMessageNotImplemented();
|
||||
return JpaResourceDao.throwProcessMessageNotImplemented();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,9 +32,8 @@ import ca.uhn.fhir.rest.annotation.Operation;
|
|||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
@ -44,6 +43,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.provider.ValueSetOperationProvider.toValidateCodeResult;
|
||||
import static ca.uhn.fhir.util.DatatypeUtil.toStringValue;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public abstract class BaseJpaResourceProviderCodeSystem<T extends IBaseResource> extends BaseJpaResourceProvider<T> {
|
||||
|
@ -115,7 +116,7 @@ public abstract class BaseJpaResourceProviderCodeSystem<T extends IBaseResource>
|
|||
}
|
||||
}
|
||||
|
||||
private static void applyVersionToSystem(IPrimitiveType<String> theSystem, IPrimitiveType<String> theVersion) {
|
||||
static void applyVersionToSystem(IPrimitiveType<String> theSystem, IPrimitiveType<String> theVersion) {
|
||||
if (theVersion != null && isNotBlank(theVersion.getValueAsString()) && theSystem != null) {
|
||||
theSystem.setValue(theSystem.getValueAsString() + "|" + theVersion.getValueAsString());
|
||||
}
|
||||
|
@ -138,7 +139,7 @@ public abstract class BaseJpaResourceProviderCodeSystem<T extends IBaseResource>
|
|||
@OperationParam(name = "code", min = 0, max = 1, typeName = "code") IPrimitiveType<String> theCode,
|
||||
@OperationParam(name = "display", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theDisplay,
|
||||
@OperationParam(name = "coding", min = 0, max = 1, typeName = "Coding") IBaseCoding theCoding,
|
||||
@OperationParam(name = "codeableConcept", min = 0, max = 1, typeName = "CodeableConcept") IBase theCodeableConcept,
|
||||
@OperationParam(name = "codeableConcept", min = 0, max = 1, typeName = "CodeableConcept") IBaseDatatype theCodeableConcept,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
|
@ -168,9 +169,9 @@ public abstract class BaseJpaResourceProviderCodeSystem<T extends IBaseResource>
|
|||
} else {
|
||||
// Otherwise, use the local DAO layer to validate the code
|
||||
IFhirResourceDaoCodeSystem dao = (IFhirResourceDaoCodeSystem) getDao();
|
||||
result = dao.validateCode(theId, theCodeSystemUrl, theVersion, theCode, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
result = dao.validateCode(theId, theCodeSystemUrl, theVersion, theCode, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
}
|
||||
return BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||
return toValidateCodeResult(getContext(), result);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import ca.uhn.fhir.rest.api.SortSpec;
|
|||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
|
||||
public abstract class BaseJpaResourceProviderEncounterDstu2 extends JpaResourceProviderDstu2<Encounter> {
|
||||
public abstract class BaseJpaResourceProviderEncounterDstu2 extends BaseJpaResourceProvider<Encounter> {
|
||||
|
||||
/**
|
||||
* Encounter/123/$everything
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||
import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public abstract class BaseJpaResourceProviderValueSetDstu2 extends JpaResourceProviderDstu2<ValueSet> {
|
||||
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_EXPAND, idempotent = true)
|
||||
public ValueSet expand(
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam(optional = true) IdDt theId,
|
||||
@OperationParam(name = "valueSet", min = 0, max = 1) ValueSet theValueSet,
|
||||
@OperationParam(name = "identifier", min = 0, max = 1) UriDt theIdentifier,
|
||||
@OperationParam(name = "filter", min = 0, max = 1) StringDt theFilter,
|
||||
RequestDetails theRequestDetails) {
|
||||
|
||||
boolean haveId = theId != null && theId.hasIdPart();
|
||||
boolean haveIdentifier = theIdentifier != null && isNotBlank(theIdentifier.getValue());
|
||||
boolean haveValueSet = theValueSet != null && theValueSet.isEmpty() == false;
|
||||
|
||||
if (!haveId && !haveIdentifier && !haveValueSet) {
|
||||
throw new InvalidRequestException(Msg.code(1130) + "$expand operation at the type level (no ID specified) requires an identifier or a valueSet as a part of the request");
|
||||
}
|
||||
|
||||
if (moreThanOneTrue(haveId, haveIdentifier, haveValueSet)) {
|
||||
throw new InvalidRequestException(Msg.code(1131) + "$expand must EITHER be invoked at the type level, or have an identifier specified, or have a ValueSet specified. Can not combine these options.");
|
||||
}
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||
if (haveId) {
|
||||
return dao.expand(theId, toFilterString(theFilter), theRequestDetails);
|
||||
} else if (haveIdentifier) {
|
||||
return dao.expandByIdentifier(theIdentifier.getValue(), toFilterString(theFilter));
|
||||
} else {
|
||||
return dao.expand(theValueSet, toFilterString(theFilter));
|
||||
}
|
||||
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
private ValueSetExpansionOptions toFilterString(StringDt theFilter) {
|
||||
if (theFilter != null) {
|
||||
return ValueSetExpansionOptions.forOffsetAndCount(0, 1000).setFilter(theFilter.getValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "name", type = StringDt.class, min = 1),
|
||||
@OperationParam(name = "version", type = StringDt.class, min = 0),
|
||||
@OperationParam(name = "display", type = StringDt.class, min = 1),
|
||||
@OperationParam(name = "abstract", type = BooleanDt.class, min = 1),
|
||||
})
|
||||
public Parameters lookup(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = "code", min = 0, max = 1) CodeDt theCode,
|
||||
@OperationParam(name = "system", min = 0, max = 1) UriDt theSystem,
|
||||
@OperationParam(name = "coding", min = 0, max = 1) CodingDt theCoding,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoCodeSystem<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoCodeSystem<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||
IValidationSupport.LookupCodeResult result = dao.lookupCode(theCode, theSystem, theCoding, null, theRequestDetails);
|
||||
if (result.isFound() == false) {
|
||||
throw new ResourceNotFoundException(Msg.code(1132) + "Unable to find code[" + result.getSearchedForCode() + "] in system[" + result.getSearchedForSystem() + "]");
|
||||
}
|
||||
Parameters retVal = new Parameters();
|
||||
retVal.addParameter().setName("name").setValue(new StringDt(result.getCodeSystemDisplayName()));
|
||||
if (isNotBlank(result.getCodeSystemVersion())) {
|
||||
retVal.addParameter().setName("version").setValue(new StringDt(result.getCodeSystemVersion()));
|
||||
}
|
||||
retVal.addParameter().setName("display").setValue(new StringDt(result.getCodeDisplay()));
|
||||
retVal.addParameter().setName("abstract").setValue(new BooleanDt(result.isCodeIsAbstract()));
|
||||
return retVal;
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_VALIDATE_CODE, idempotent = true, returnParameters = {
|
||||
@OperationParam(name = "result", type = BooleanDt.class, min = 1),
|
||||
@OperationParam(name = "message", type = StringDt.class),
|
||||
@OperationParam(name = "display", type = StringDt.class)
|
||||
})
|
||||
public Parameters validateCode(
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam(optional = true) IdDt theId,
|
||||
@OperationParam(name = "identifier", min = 0, max = 1) UriDt theValueSetIdentifier,
|
||||
@OperationParam(name = "code", min = 0, max = 1) CodeDt theCode,
|
||||
@OperationParam(name = "system", min = 0, max = 1) UriDt theSystem,
|
||||
@OperationParam(name = "display", min = 0, max = 1) StringDt theDisplay,
|
||||
@OperationParam(name = "coding", min = 0, max = 1) CodingDt theCoding,
|
||||
@OperationParam(name = "codeableConcept", min = 0, max = 1) CodeableConceptDt theCodeableConcept,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt> dao = (IFhirResourceDaoValueSet<ValueSet, CodingDt, CodeableConceptDt>) getDao();
|
||||
IValidationSupport.CodeValidationResult result = dao.validateCode(theValueSetIdentifier, theId, theCode, theSystem, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
return (Parameters) toValidateCodeResult(getContext(), result);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
public static IBaseParameters toValidateCodeResult(FhirContext theContext, IValidationSupport.CodeValidationResult theResult) {
|
||||
IBaseParameters retVal = ParametersUtil.newInstance(theContext);
|
||||
|
||||
ParametersUtil.addParameterToParametersBoolean(theContext, retVal, "result", theResult.isOk());
|
||||
if (isNotBlank(theResult.getMessage())) {
|
||||
ParametersUtil.addParameterToParametersString(theContext, retVal, "message", theResult.getMessage());
|
||||
}
|
||||
if (isNotBlank(theResult.getDisplay())) {
|
||||
ParametersUtil.addParameterToParametersString(theContext, retVal, "display", theResult.getDisplay());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static boolean moreThanOneTrue(boolean... theBooleans) {
|
||||
boolean haveOne = false;
|
||||
for (boolean next : theBooleans) {
|
||||
if (next) {
|
||||
if (haveOne) {
|
||||
return true;
|
||||
} else {
|
||||
haveOne = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -102,29 +102,6 @@ public final class JpaSystemProvider<T, MT> extends BaseJpaSystemProvider<T, MT>
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* $process-message
|
||||
*/
|
||||
@Description("Accept a FHIR Message Bundle for processing")
|
||||
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
|
||||
public IBaseBundle processMessage(
|
||||
HttpServletRequest theServletRequest,
|
||||
RequestDetails theRequestDetails,
|
||||
|
||||
@OperationParam(name = "content", min = 1, max = 1, typeName = "Bundle")
|
||||
@Description(formalDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
|
||||
IBaseBundle theMessageToProcess
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
return getDao().processMessage(theRequestDetails, theMessageToProcess);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Operation(name = JpaConstants.OPERATION_GET_RESOURCE_COUNTS, idempotent = true)
|
||||
@Description(shortDefinition = "Provides the number of resources currently stored on the server, broken down by resource type")
|
||||
public IBaseParameters getResourceCounts() {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.model.api.annotation.Description;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static ca.uhn.fhir.jpa.provider.BaseJpaProvider.endRequest;
|
||||
import static ca.uhn.fhir.jpa.provider.BaseJpaProvider.startRequest;
|
||||
|
||||
public class ProcessMessageProvider {
|
||||
|
||||
@Autowired
|
||||
private IFhirSystemDao<?, ?> mySystemDao;
|
||||
|
||||
/**
|
||||
* $process-message
|
||||
*/
|
||||
@Description("Accept a FHIR Message Bundle for processing")
|
||||
@Operation(name = JpaConstants.OPERATION_PROCESS_MESSAGE, idempotent = false)
|
||||
public IBaseBundle processMessage(
|
||||
HttpServletRequest theServletRequest,
|
||||
RequestDetails theRequestDetails,
|
||||
|
||||
@OperationParam(name = "content", min = 1, max = 1, typeName = "Bundle")
|
||||
@Description(shortDefinition = "The message to process (or, if using asynchronous messaging, it may be a response message to accept)")
|
||||
IBaseBundle theMessageToProcess
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
return mySystemDao.processMessage(theRequestDetails, theMessageToProcess);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.provider;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
|
@ -29,20 +30,17 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
|||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoValueSet;
|
||||
import ca.uhn.fhir.jpa.config.JpaConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.search.autocomplete.ValueSetAutocompleteOptions;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||
import ca.uhn.fhir.util.ParametersUtil;
|
||||
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.ICompositeType;
|
||||
|
@ -55,12 +53,15 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static ca.uhn.fhir.util.DatatypeUtil.toStringValue;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class ValueSetOperationProvider extends BaseJpaProvider {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(ValueSetOperationProvider.class);
|
||||
@Autowired
|
||||
protected IValidationSupport myValidationSupport;
|
||||
@Autowired
|
||||
private DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
|
@ -69,10 +70,6 @@ public class ValueSetOperationProvider extends BaseJpaProvider {
|
|||
@Autowired
|
||||
@Qualifier(JpaConfig.JPA_VALIDATION_SUPPORT_CHAIN)
|
||||
private ValidationSupportChain myValidationSupportChain;
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
@Autowired(required = false)
|
||||
private IFulltextSearchSvc myFulltextSearch;
|
||||
|
||||
public void setValidationSupport(IValidationSupport theValidationSupport) {
|
||||
myValidationSupport = theValidationSupport;
|
||||
|
@ -110,70 +107,10 @@ public class ValueSetOperationProvider extends BaseJpaProvider {
|
|||
@OperationParam(name = JpaConstants.OPERATION_EXPAND_PARAM_INCLUDE_HIERARCHY, min = 0, max = 1, typeName = "boolean") IPrimitiveType<Boolean> theIncludeHierarchy,
|
||||
RequestDetails theRequestDetails) {
|
||||
|
||||
boolean haveId = theId != null && theId.hasIdPart();
|
||||
boolean haveIdentifier = theUrl != null && isNotBlank(theUrl.getValue());
|
||||
boolean haveValueSet = theValueSet != null && !theValueSet.isEmpty();
|
||||
boolean haveValueSetVersion = theValueSetVersion != null && !theValueSetVersion.isEmpty();
|
||||
boolean haveContextDirection = theContextDirection != null && !theContextDirection.isEmpty();
|
||||
boolean haveContext = theContext != null && !theContext.isEmpty();
|
||||
|
||||
boolean isAutocompleteExtension = haveContext && haveContextDirection && "existing".equals(theContextDirection.getValue());
|
||||
|
||||
if (isAutocompleteExtension) {
|
||||
// this is a funky extension for NIH. Do our own thing and return.
|
||||
ValueSetAutocompleteOptions options = ValueSetAutocompleteOptions.validateAndParseOptions(myDaoConfig, theContext, theFilter, theCount, theId, theUrl, theValueSet);
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
if (myFulltextSearch == null || myFulltextSearch.isDisabled()) {
|
||||
throw new InvalidRequestException(Msg.code(2083) + " Autocomplete is not supported on this server, as the fulltext search service is not configured.");
|
||||
} else {
|
||||
return myFulltextSearch.tokenAutocompleteValueSetSearch(options);
|
||||
}
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
if (!haveId && !haveIdentifier && !haveValueSet) {
|
||||
throw new InvalidRequestException(Msg.code(1133) + "$expand operation at the type level (no ID specified) requires a url or a valueSet as a part of the request.");
|
||||
}
|
||||
|
||||
if (moreThanOneTrue(haveId, haveIdentifier, haveValueSet)) {
|
||||
throw new InvalidRequestException(Msg.code(1134) + "$expand must EITHER be invoked at the instance level, or have a url specified, or have a ValueSet specified. Can not combine these options.");
|
||||
}
|
||||
|
||||
ValueSetExpansionOptions options = createValueSetExpansionOptions(myDaoConfig, theOffset, theCount, theIncludeHierarchy, theFilter, theDisplayLanguage);
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
|
||||
IFhirResourceDaoValueSet<IBaseResource, ICompositeType, ICompositeType> dao = getDao();
|
||||
|
||||
IValidationSupport.ValueSetExpansionOutcome outcome;
|
||||
if (haveId) {
|
||||
IBaseResource valueSet = dao.read(theId, theRequestDetails);
|
||||
outcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, valueSet);
|
||||
} else if (haveIdentifier) {
|
||||
String url;
|
||||
if (haveValueSetVersion) {
|
||||
url = theUrl.getValue() + "|" + theValueSetVersion.getValue();
|
||||
} else {
|
||||
url = theUrl.getValue();
|
||||
}
|
||||
outcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, url);
|
||||
} else {
|
||||
outcome = myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), options, theValueSet);
|
||||
}
|
||||
|
||||
if (outcome == null) {
|
||||
throw new InternalErrorException(Msg.code(2028) + "No validation support module was able to expand the given valueset");
|
||||
}
|
||||
|
||||
if (outcome.getError() != null) {
|
||||
throw new PreconditionFailedException(Msg.code(2029) + outcome.getError());
|
||||
}
|
||||
|
||||
return outcome.getValueSet();
|
||||
return getDao().expand(theId, theValueSet, theUrl, theValueSetVersion, theFilter, theContext, theContextDirection, theOffset, theCount, theDisplayLanguage, theIncludeHierarchy, theRequestDetails);
|
||||
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
|
@ -181,8 +118,8 @@ public class ValueSetOperationProvider extends BaseJpaProvider {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private IFhirResourceDaoValueSet<IBaseResource, ICompositeType, ICompositeType> getDao() {
|
||||
return (IFhirResourceDaoValueSet<IBaseResource, ICompositeType, ICompositeType>) myDaoRegistry.getResourceDao("ValueSet");
|
||||
protected IFhirResourceDaoValueSet<IBaseResource> getDao() {
|
||||
return (IFhirResourceDaoValueSet<IBaseResource>) myDaoRegistry.getResourceDao("ValueSet");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -196,11 +133,11 @@ public class ValueSetOperationProvider extends BaseJpaProvider {
|
|||
@IdParam(optional = true) IIdType theId,
|
||||
@OperationParam(name = "url", min = 0, max = 1, typeName = "uri") IPrimitiveType<String> theValueSetUrl,
|
||||
@OperationParam(name = "valueSetVersion", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theValueSetVersion,
|
||||
@OperationParam(name = "code", min = 0, max = 1) IPrimitiveType<String> theCode,
|
||||
@OperationParam(name = "code", min = 0, max = 1, typeName = "code") IPrimitiveType<String> theCode,
|
||||
@OperationParam(name = "system", min = 0, max = 1, typeName = "uri") IPrimitiveType<String> theSystem,
|
||||
@OperationParam(name = "systemVersion", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theSystemVersion,
|
||||
@OperationParam(name = "display", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theDisplay,
|
||||
@OperationParam(name = "coding", min = 0, max = 1, typeName = "Coding") ICompositeType theCoding,
|
||||
@OperationParam(name = "coding", min = 0, max = 1, typeName = "Coding") IBaseCoding theCoding,
|
||||
@OperationParam(name = "codeableConcept", min = 0, max = 1, typeName = "CodeableConcept") ICompositeType theCodeableConcept,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
@ -219,7 +156,7 @@ public class ValueSetOperationProvider extends BaseJpaProvider {
|
|||
new ConceptValidationOptions(), theSystemString, theCodeString, theDisplayString, theValueSetUrlString);
|
||||
} else {
|
||||
// Otherwise, use the local DAO layer to validate the code
|
||||
IFhirResourceDaoValueSet<IBaseResource, ICompositeType, ICompositeType> dao = getDao();
|
||||
IFhirResourceDaoValueSet<IBaseResource> dao = getDao();
|
||||
IPrimitiveType<String> valueSetIdentifier;
|
||||
if (theValueSetUrl != null && theValueSetVersion != null) {
|
||||
valueSetIdentifier = (IPrimitiveType<String>) getContext().getElementDefinition("uri").newInstance();
|
||||
|
@ -236,7 +173,7 @@ public class ValueSetOperationProvider extends BaseJpaProvider {
|
|||
}
|
||||
result = dao.validateCode(valueSetIdentifier, theId, theCode, codeSystemIdentifier, theDisplay, theCoding, theCodeableConcept, theRequestDetails);
|
||||
}
|
||||
return BaseJpaResourceProviderValueSetDstu2.toValidateCodeResult(getContext(), result);
|
||||
return toValidateCodeResult(getContext(), result);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
|
@ -298,25 +235,26 @@ public class ValueSetOperationProvider extends BaseJpaProvider {
|
|||
options.setFilter(theFilter.getValue());
|
||||
}
|
||||
|
||||
if( theDisplayLanguage != null ) {
|
||||
if (theDisplayLanguage != null) {
|
||||
options.setTheDisplayLanguage(theDisplayLanguage.getValue());
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private static boolean moreThanOneTrue(boolean... theBooleans) {
|
||||
boolean haveOne = false;
|
||||
for (boolean next : theBooleans) {
|
||||
if (next) {
|
||||
if (haveOne) {
|
||||
return true;
|
||||
} else {
|
||||
haveOne = true;
|
||||
}
|
||||
}
|
||||
public static IBaseParameters toValidateCodeResult(FhirContext theContext, IValidationSupport.CodeValidationResult theResult) {
|
||||
IBaseParameters retVal = ParametersUtil.newInstance(theContext);
|
||||
|
||||
ParametersUtil.addParameterToParametersBoolean(theContext, retVal, "result", theResult.isOk());
|
||||
if (isNotBlank(theResult.getMessage())) {
|
||||
ParametersUtil.addParameterToParametersString(theContext, retVal, "message", theResult.getMessage());
|
||||
}
|
||||
return false;
|
||||
if (isNotBlank(theResult.getDisplay())) {
|
||||
ParametersUtil.addParameterToParametersString(theContext, retVal, "display", theResult.getDisplay());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
package ca.uhn.fhir.jpa.provider;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.jpa.dao.JpaResourceDaoCodeSystem;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
import static ca.uhn.fhir.jpa.provider.BaseJpaResourceProviderCodeSystem.applyVersionToSystem;
|
||||
|
||||
public class ValueSetOperationProviderDstu2 extends ValueSetOperationProvider {
|
||||
|
||||
@Autowired
|
||||
private IValidationSupport myValidationSupport;
|
||||
|
||||
/**
|
||||
* Alternate expand implementation since DSTU2 uses "identifier" instead of "url" as a parameter.
|
||||
*/
|
||||
@Operation(name = JpaConstants.OPERATION_EXPAND, idempotent = true, typeName = "ValueSet")
|
||||
public IBaseResource expand(
|
||||
HttpServletRequest theServletRequest,
|
||||
@IdParam(optional = true) IIdType theId,
|
||||
@OperationParam(name = "valueSet", min = 0, max = 1) IBaseResource theValueSet,
|
||||
@OperationParam(name = "url", min = 0, max = 1, typeName = "uri") IPrimitiveType<String> theUrl,
|
||||
@OperationParam(name = "identifier", min = 0, max = 1, typeName = "uri") IPrimitiveType<String> theIdentifier,
|
||||
@OperationParam(name = "valueSetVersion", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theValueSetVersion,
|
||||
@OperationParam(name = "filter", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theFilter,
|
||||
@OperationParam(name = "context", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theContext,
|
||||
@OperationParam(name = "contextDirection", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theContextDirection,
|
||||
@OperationParam(name = "offset", min = 0, max = 1, typeName = "integer") IPrimitiveType<Integer> theOffset,
|
||||
@OperationParam(name = "count", min = 0, max = 1, typeName = "integer") IPrimitiveType<Integer> theCount,
|
||||
@OperationParam(name = JpaConstants.OPERATION_EXPAND_PARAM_DISPLAY_LANGUAGE, min = 0, max = 1, typeName = "code") IPrimitiveType<String> theDisplayLanguage,
|
||||
@OperationParam(name = JpaConstants.OPERATION_EXPAND_PARAM_INCLUDE_HIERARCHY, min = 0, max = 1, typeName = "boolean") IPrimitiveType<Boolean> theIncludeHierarchy,
|
||||
RequestDetails theRequestDetails) {
|
||||
|
||||
IPrimitiveType<String> url = theUrl;
|
||||
if (theIdentifier != null) {
|
||||
url = theIdentifier;
|
||||
}
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
|
||||
return getDao().expand(theId, theValueSet, url, theValueSetVersion, theFilter, theContext, theContextDirection, theOffset, theCount, theDisplayLanguage, theIncludeHierarchy, theRequestDetails);
|
||||
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* $lookup operation - This is on CodeSystem after DSTU2 but on ValueSet in DSTU2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Operation(name = JpaConstants.OPERATION_LOOKUP, idempotent = true, typeName = "ValueSet", returnParameters = {
|
||||
@OperationParam(name = "name", typeName = "string", min = 1),
|
||||
@OperationParam(name = "version", typeName = "string", min = 0),
|
||||
@OperationParam(name = "display", typeName = "string", min = 1),
|
||||
@OperationParam(name = "abstract", typeName = "boolean", min = 1),
|
||||
})
|
||||
public IBaseParameters lookup(
|
||||
HttpServletRequest theServletRequest,
|
||||
@OperationParam(name = "code", min = 0, max = 1, typeName = "code") IPrimitiveType<String> theCode,
|
||||
@OperationParam(name = "system", min = 0, max = 1, typeName = "uri") IPrimitiveType<String> theSystem,
|
||||
@OperationParam(name = "coding", min = 0, max = 1, typeName = "Coding") IBaseCoding theCoding,
|
||||
@OperationParam(name = "version", min = 0, max = 1, typeName = "string") IPrimitiveType<String> theVersion,
|
||||
@OperationParam(name = "displayLanguage", min = 0, max = 1, typeName = "code") IPrimitiveType<String> theDisplayLanguage,
|
||||
@OperationParam(name = "property", min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "code") List<IPrimitiveType<String>> theProperties,
|
||||
RequestDetails theRequestDetails
|
||||
) {
|
||||
|
||||
startRequest(theServletRequest);
|
||||
try {
|
||||
IValidationSupport.LookupCodeResult result;
|
||||
applyVersionToSystem(theSystem, theVersion);
|
||||
|
||||
FhirTerser terser = getContext().newTerser();
|
||||
result = JpaResourceDaoCodeSystem.doLookupCode(getContext(), terser, myValidationSupport, theCode, theSystem, theCoding, theDisplayLanguage);
|
||||
result.throwNotFoundIfAppropriate();
|
||||
return result.toParameters(theRequestDetails.getFhirContext(), theProperties);
|
||||
} finally {
|
||||
endRequest(theServletRequest);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||
|
||||
public abstract class BaseJpaResourceProviderValueSetDstu3 extends BaseJpaResourceProvider<ValueSet> {
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
public abstract class BaseJpaResourceProviderValueSetR4 extends BaseJpaResourceProvider<ValueSet> {
|
||||
|
||||
}
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4b;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||
import org.hl7.fhir.r4b.model.ValueSet;
|
||||
|
||||
public abstract class BaseJpaResourceProviderValueSetR4B extends BaseJpaResourceProvider<ValueSet> {
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package ca.uhn.fhir.jpa.provider.r5;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
|
||||
public abstract class BaseJpaResourceProviderValueSetR5 extends BaseJpaResourceProvider<ValueSet> {
|
||||
// nothing
|
||||
}
|
|
@ -691,7 +691,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
for (String type : resourceTypes) {
|
||||
String trimmed = type.trim();
|
||||
if (!knownResourceTypes.contains(trimmed)) {
|
||||
throw new ResourceNotFoundException(Msg.code(2132) + "Unknown resource type '" + trimmed + "' in _type parameter.");
|
||||
throw new ResourceNotFoundException(Msg.code(2197) + "Unknown resource type '" + trimmed + "' in _type parameter.");
|
||||
}
|
||||
retVal.add(trimmed);
|
||||
}
|
||||
|
|
|
@ -423,7 +423,7 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
|
|||
}
|
||||
|
||||
ourLog.debug("Done saving concepts, flushing to database");
|
||||
if (!myDeferredStorageSvc.isStorageQueueEmpty()) {
|
||||
if (!myDeferredStorageSvc.isStorageQueueEmpty(true)) {
|
||||
ourLog.info("Note that some concept saving has been deferred");
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
|
|||
|
||||
ourLog.info("Saving concept {} with parent {}", theStatisticsTracker.getUpdatedConceptCount(), parentDescription);
|
||||
|
||||
Optional<TermConcept> existingCodeOpt = myConceptDao.findByCodeSystemAndCode(theCsv, nextCodeToAdd);
|
||||
Optional<TermConcept> existingCodeOpt = myConceptDao.findByCodeSystemAndCode(theCsv.getPid(), nextCodeToAdd);
|
||||
List<TermConceptParentChildLink> existingParentLinks;
|
||||
if (existingCodeOpt.isPresent()) {
|
||||
TermConcept existingCode = existingCodeOpt.get();
|
||||
|
@ -476,7 +476,7 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
|
|||
|
||||
TermConcept nextParentOpt = theCodeToConcept.get(nextParentCode);
|
||||
if (nextParentOpt == null) {
|
||||
nextParentOpt = myConceptDao.findByCodeSystemAndCode(theCsv, nextParentCode).orElse(null);
|
||||
nextParentOpt = myConceptDao.findByCodeSystemAndCode(theCsv.getPid(), nextParentCode).orElse(null);
|
||||
}
|
||||
if (nextParentOpt == null) {
|
||||
throw new InvalidRequestException(Msg.code(846) + "Unable to add code \"" + nextCodeToAdd + "\" to unknown parent: " + nextParentCode);
|
||||
|
@ -542,7 +542,7 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
|
|||
String parentCode = nextChild.getParents().get(i).getParent().getCode();
|
||||
TermConcept parentConcept = theCodeToConcept.get(parentCode);
|
||||
if (parentConcept == null) {
|
||||
parentConcept = myConceptDao.findByCodeSystemAndCode(theCsv, parentCode).orElse(null);
|
||||
parentConcept = myConceptDao.findByCodeSystemAndCode(theCsv.getPid(), parentCode).orElse(null);
|
||||
}
|
||||
if (parentConcept == null) {
|
||||
throw new IllegalArgumentException(Msg.code(847) + "Unknown parent code: " + parentCode);
|
||||
|
|
|
@ -282,7 +282,9 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
|
|||
Duration.of(SAVE_ALL_DEFERRED_ERROR_MINUTES, ChronoUnit.MINUTES));
|
||||
}
|
||||
|
||||
while (!isStorageQueueEmpty()) {
|
||||
// Don't include executing jobs here since there's no point in thrashing over and over
|
||||
// in a busy wait while we wait for batch2 job processes to finish
|
||||
while (!isStorageQueueEmpty(false)) {
|
||||
if (myAllowDeferredTasksTimeout) {
|
||||
if (timeoutManager.checkTimeout()) {
|
||||
ourLog.info(toString());
|
||||
|
@ -389,14 +391,16 @@ public class TermDeferredStorageSvcImpl implements ITermDeferredStorageSvc {
|
|||
|
||||
|
||||
@Override
|
||||
public boolean isStorageQueueEmpty() {
|
||||
public boolean isStorageQueueEmpty(boolean theIncludeExecutingJobs) {
|
||||
boolean retVal = !isProcessDeferredPaused();
|
||||
retVal &= !isDeferredConcepts();
|
||||
retVal &= !isConceptLinksToSaveLater();
|
||||
retVal &= !isDeferredValueSets();
|
||||
retVal &= !isDeferredConceptMaps();
|
||||
retVal &= !isDeferredCodeSystemDeletions();
|
||||
retVal &= !isJobsExecuting();
|
||||
if (theIncludeExecutingJobs) {
|
||||
retVal &= !isJobsExecuting();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.term;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.support.ConceptValidationOptions;
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.context.support.ValidationSupportContext;
|
||||
|
@ -70,7 +71,6 @@ import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
|||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ReindexTerminologyResult;
|
||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||
import ca.uhn.fhir.jpa.util.LogicUtil;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
|
@ -108,13 +108,12 @@ import org.hibernate.search.mapper.orm.Search;
|
|||
import org.hibernate.search.mapper.orm.common.EntityReference;
|
||||
import org.hibernate.search.mapper.orm.session.SearchSession;
|
||||
import org.hibernate.search.mapper.pojo.massindexing.impl.PojoMassIndexingLoggingMonitor;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTerminologyService;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
|
||||
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
|
||||
import org.hl7.fhir.convertors.context.ConversionContext40_50;
|
||||
import org.hl7.fhir.convertors.conv40_50.VersionConvertor_40_50;
|
||||
import org.hl7.fhir.convertors.conv40_50.resources40_50.ValueSet40_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
|
@ -158,14 +157,6 @@ import javax.persistence.EntityManager;
|
|||
import javax.persistence.NonUniqueResultException;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Fetch;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -175,7 +166,6 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -200,14 +190,13 @@ import static org.apache.commons.lang3.StringUtils.isNoneBlank;
|
|||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.lowerCase;
|
||||
import static org.apache.commons.lang3.StringUtils.startsWithIgnoreCase;
|
||||
import static org.hl7.fhir.common.hapi.validation.support.ValidationConstants.LOINC_LOW;
|
||||
|
||||
public class TermReadSvcImpl implements ITermReadSvc {
|
||||
public static final int DEFAULT_FETCH_SIZE = 250;
|
||||
private static final int SINGLE_FETCH_SIZE = 1;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TermReadSvcImpl.class);
|
||||
private static final ValueSetExpansionOptions DEFAULT_EXPANSION_OPTIONS = new ValueSetExpansionOptions();
|
||||
private static final TermCodeSystemVersion NO_CURRENT_VERSION = new TermCodeSystemVersion().setId(-1L);
|
||||
private static final TermCodeSystemVersionDetails NO_CURRENT_VERSION = new TermCodeSystemVersionDetails(-1L, null);
|
||||
private static Runnable myInvokeOnNextCallForUnitTest;
|
||||
private static boolean ourForceDisableHibernateSearchForUnitTest;
|
||||
|
||||
|
@ -222,7 +211,7 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
private boolean myPreExpandingValueSets = false;
|
||||
|
||||
private final Cache<String, TermCodeSystemVersion> myCodeSystemCurrentVersionCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
|
||||
private final Cache<String, TermCodeSystemVersionDetails> myCodeSystemCurrentVersionCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
|
||||
@Autowired
|
||||
protected DaoRegistry myDaoRegistry;
|
||||
@Autowired
|
||||
|
@ -276,11 +265,13 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
//We need this bean so we can tell which mode hibernate search is running in.
|
||||
@Autowired
|
||||
private HibernatePropertiesProvider myHibernatePropertiesProvider;
|
||||
@Autowired
|
||||
private CachingValidationSupport myCachingValidationSupport;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isCodeSystemSupported(ValidationSupportContext theValidationSupportContext, String theSystem) {
|
||||
TermCodeSystemVersion cs = getCurrentCodeSystemVersion(theSystem);
|
||||
TermCodeSystemVersionDetails cs = getCurrentCodeSystemVersion(theSystem);
|
||||
return cs != null;
|
||||
}
|
||||
|
||||
|
@ -831,7 +822,6 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
expandValueSetHandleIncludeOrExcludeUsingDatabase(theExpansionOptions, theValueSetCodeAccumulator,
|
||||
theAddedCodes, theIncludeOrExclude, theAdd, theExpansionFilter, system, cs);
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -1617,6 +1607,9 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
termValueSet.setExpansionStatus(TermValueSetPreExpansionStatusEnum.NOT_EXPANDED);
|
||||
termValueSet.setExpansionTimestamp(null);
|
||||
myTermValueSetDao.save(termValueSet);
|
||||
|
||||
afterValueSetExpansionStatusChange();
|
||||
|
||||
return myContext.getLocalizer().getMessage(TermReadSvcImpl.class, "valueSetPreExpansionInvalidated", termValueSet.getUrl(), totalConcepts);
|
||||
}
|
||||
|
||||
|
@ -1700,7 +1693,9 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
}
|
||||
|
||||
return createFailureCodeValidationResult(theSystem, theCode, systemVersion, " - Concept Display \"" + theDisplay + "\" does not match expected \"" + concepts.get(0).getDisplay() + "\". " + msg).setDisplay(concepts.get(0).getDisplay());
|
||||
String expectedDisplay = concepts.get(0).getDisplay();
|
||||
String append = createMessageAppendForDisplayMismatch(theSystem, theDisplay, expectedDisplay) + " - " + msg;
|
||||
return createFailureCodeValidationResult(theSystem, theCode, systemVersion, append).setDisplay(expectedDisplay);
|
||||
}
|
||||
|
||||
if (!concepts.isEmpty()) {
|
||||
|
@ -1758,7 +1753,7 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
private Optional<TermConcept> fetchLoadedCode(Long theCodeSystemResourcePid, String theCode) {
|
||||
TermCodeSystemVersion codeSystem = myCodeSystemVersionDao.findCurrentVersionForCodeSystemResourcePid(theCodeSystemResourcePid);
|
||||
return myConceptDao.findByCodeSystemAndCode(codeSystem, theCode);
|
||||
return myConceptDao.findByCodeSystemAndCode(codeSystem.getPid(), theCode);
|
||||
}
|
||||
|
||||
private void fetchParents(TermConcept theConcept, Set<TermConcept> theSetToPopulate) {
|
||||
|
@ -1780,31 +1775,31 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
*/
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_MANDATORY);
|
||||
txTemplate.setReadOnly(true);
|
||||
|
||||
return txTemplate.execute(t -> {
|
||||
TermCodeSystemVersion csv = getCurrentCodeSystemVersion(theCodeSystem);
|
||||
TermCodeSystemVersionDetails csv = getCurrentCodeSystemVersion(theCodeSystem);
|
||||
if (csv == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return myConceptDao.findByCodeSystemAndCode(csv, theCode);
|
||||
return myConceptDao.findByCodeSystemAndCode(csv.myPid, theCode);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.MANDATORY)
|
||||
public List<TermConcept> findCodes(String theCodeSystem, List<String> theCodeList) {
|
||||
TermCodeSystemVersion csv = getCurrentCodeSystemVersion(theCodeSystem);
|
||||
TermCodeSystemVersionDetails csv = getCurrentCodeSystemVersion(theCodeSystem);
|
||||
if (csv == null) { return Collections.emptyList(); }
|
||||
|
||||
return myConceptDao.findByCodeSystemAndCodeList(csv, theCodeList);
|
||||
return myConceptDao.findByCodeSystemAndCodeList(csv.myPid, theCodeList);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private TermCodeSystemVersion getCurrentCodeSystemVersion(String theCodeSystemIdentifier) {
|
||||
private TermCodeSystemVersionDetails getCurrentCodeSystemVersion(String theCodeSystemIdentifier) {
|
||||
String version = getVersionFromIdentifier(theCodeSystemIdentifier);
|
||||
TermCodeSystemVersion retVal = myCodeSystemCurrentVersionCache.get(theCodeSystemIdentifier, t -> myTxTemplate.execute(tx -> {
|
||||
TermCodeSystemVersionDetails retVal = myCodeSystemCurrentVersionCache.get(theCodeSystemIdentifier, t -> myTxTemplate.execute(tx -> {
|
||||
TermCodeSystemVersion csv = null;
|
||||
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(getUrlFromIdentifier(theCodeSystemIdentifier));
|
||||
if (cs != null) {
|
||||
|
@ -1815,7 +1810,7 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
}
|
||||
if (csv != null) {
|
||||
return csv;
|
||||
return new TermCodeSystemVersionDetails(csv.getPid(), csv.getCodeSystemVersionId());
|
||||
} else {
|
||||
return NO_CURRENT_VERSION;
|
||||
}
|
||||
|
@ -1826,6 +1821,19 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
private static class TermCodeSystemVersionDetails {
|
||||
|
||||
|
||||
private final long myPid;
|
||||
private final String myCodeSystemVersionId;
|
||||
|
||||
public TermCodeSystemVersionDetails(long thePid, String theCodeSystemVersionId) {
|
||||
myPid = thePid;
|
||||
myCodeSystemVersionId = theCodeSystemVersionId;
|
||||
}
|
||||
}
|
||||
|
||||
private String getVersionFromIdentifier(String theUri) {
|
||||
String retVal = null;
|
||||
if (StringUtils.isNotEmpty((theUri))) {
|
||||
|
@ -1984,6 +1992,8 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
});
|
||||
|
||||
afterValueSetExpansionStatusChange();
|
||||
|
||||
ourLog.info("Pre-expanded ValueSet[{}] with URL[{}] - Saved {} concepts in {}", valueSet.getId(), valueSet.getUrl(), accumulator.getConceptsSaved(), sw);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
@ -2000,6 +2010,17 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a ValueSet has just finished pre-expanding, let's flush the caches. This is
|
||||
* kind of a blunt tool, but it should ensure that users don't get unpredictable
|
||||
* results while they test changes, which is probably a worthwhile sacrifice
|
||||
*/
|
||||
private void afterValueSetExpansionStatusChange() {
|
||||
// TODO: JA2 - Move this caching into the memorycacheservice, and only purge the
|
||||
// relevant individual cache
|
||||
myCachingValidationSupport.invalidateCaches();
|
||||
}
|
||||
|
||||
private synchronized void setPreExpandingValueSets(boolean thePreExpandingValueSets) {
|
||||
myPreExpandingValueSets = thePreExpandingValueSets;
|
||||
}
|
||||
|
@ -2008,77 +2029,9 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
return myPreExpandingValueSets;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CodeValidationResult validateCode(ConceptValidationOptions theOptions, IIdType theValueSetId, String theValueSetIdentifier, String theCodeSystemIdentifierToValidate, String theCodeToValidate, String theDisplayToValidate, IBaseDatatype theCodingToValidate, IBaseDatatype theCodeableConceptToValidate) {
|
||||
|
||||
CodeableConcept codeableConcept = myVersionCanonicalizer.codeableConceptToCanonical(theCodeableConceptToValidate);
|
||||
boolean haveCodeableConcept = codeableConcept != null && codeableConcept.getCoding().size() > 0;
|
||||
|
||||
Coding canonicalCodingToValidate = myVersionCanonicalizer.codingToCanonical((IBaseCoding) theCodingToValidate);
|
||||
boolean haveCoding = canonicalCodingToValidate != null && !canonicalCodingToValidate.isEmpty();
|
||||
|
||||
boolean haveCode = theCodeToValidate != null && !theCodeToValidate.isEmpty();
|
||||
|
||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
||||
throw new InvalidRequestException(Msg.code(899) + "No code, coding, or codeableConcept provided to validate");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(900) + "$validate-code can only validate (system AND code) OR (coding) OR (codeableConcept)");
|
||||
}
|
||||
|
||||
boolean haveIdentifierParam = isNotBlank(theValueSetIdentifier);
|
||||
String valueSetIdentifier;
|
||||
if (theValueSetId != null) {
|
||||
IBaseResource valueSet = myDaoRegistry.getResourceDao("ValueSet").read(theValueSetId);
|
||||
StringBuilder valueSetIdentifierBuilder = new StringBuilder(CommonCodeSystemsTerminologyService.getValueSetUrl(valueSet));
|
||||
String valueSetVersion = CommonCodeSystemsTerminologyService.getValueSetVersion(valueSet);
|
||||
if (valueSetVersion != null) {
|
||||
valueSetIdentifierBuilder.append("|").append(valueSetVersion);
|
||||
}
|
||||
valueSetIdentifier = valueSetIdentifierBuilder.toString();
|
||||
|
||||
} else if (haveIdentifierParam) {
|
||||
valueSetIdentifier = theValueSetIdentifier;
|
||||
} else {
|
||||
throw new InvalidRequestException(Msg.code(901) + "Either ValueSet ID or ValueSet identifier or system and code must be provided. Unable to validate.");
|
||||
}
|
||||
|
||||
ValidationSupportContext validationContext = new ValidationSupportContext(provideValidationSupport());
|
||||
|
||||
String codeValueToValidate = theCodeToValidate;
|
||||
String codeSystemIdentifierValueToValidate = theCodeSystemIdentifierToValidate;
|
||||
String codeDisplayValueToValidate = theDisplayToValidate;
|
||||
|
||||
if (haveCodeableConcept) {
|
||||
for (int i = 0; i < codeableConcept.getCoding().size(); i++) {
|
||||
Coding nextCoding = codeableConcept.getCoding().get(i);
|
||||
String codeSystemIdentifier;
|
||||
if (nextCoding.hasVersion()) {
|
||||
codeSystemIdentifier = nextCoding.getSystem() + "|" + nextCoding.getVersion();
|
||||
} else {
|
||||
codeSystemIdentifier = nextCoding.getSystem();
|
||||
}
|
||||
CodeValidationResult nextValidation = validateCode(validationContext, theOptions, codeSystemIdentifier, nextCoding.getCode(), nextCoding.getDisplay(), valueSetIdentifier);
|
||||
if (nextValidation.isOk() || i == codeableConcept.getCoding().size() - 1) {
|
||||
return nextValidation;
|
||||
}
|
||||
}
|
||||
} else if (haveCoding) {
|
||||
if (canonicalCodingToValidate.hasVersion()) {
|
||||
codeSystemIdentifierValueToValidate = canonicalCodingToValidate.getSystem() + "|" + canonicalCodingToValidate.getVersion();
|
||||
} else {
|
||||
codeSystemIdentifierValueToValidate = canonicalCodingToValidate.getSystem();
|
||||
}
|
||||
codeValueToValidate = canonicalCodingToValidate.getCode();
|
||||
codeDisplayValueToValidate = canonicalCodingToValidate.getDisplay();
|
||||
}
|
||||
|
||||
return validateCode(validationContext, theOptions, codeSystemIdentifierValueToValidate, codeValueToValidate, codeDisplayValueToValidate, valueSetIdentifier);
|
||||
}
|
||||
|
||||
private boolean isNotSafeToPreExpandValueSets() {
|
||||
return myDeferredStorageSvc != null && !myDeferredStorageSvc.isStorageQueueEmpty();
|
||||
return myDeferredStorageSvc != null && !myDeferredStorageSvc.isStorageQueueEmpty(true);
|
||||
}
|
||||
|
||||
private Optional<TermValueSet> getNextTermValueSetNotExpanded() {
|
||||
|
@ -2289,30 +2242,35 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public IValidationSupport.CodeValidationResult validateCode(@Nonnull ValidationSupportContext theValidationSupportContext, @Nonnull ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, String theValueSetUrl) {
|
||||
public IValidationSupport.CodeValidationResult validateCode(@Nonnull ValidationSupportContext theValidationSupportContext, @Nonnull ConceptValidationOptions theOptions, String theCodeSystemUrl, String theCode, String theDisplay, String theValueSetUrl) {
|
||||
//TODO GGG TRY TO JUST AUTO_PASS HERE AND SEE WHAT HAPPENS.
|
||||
invokeRunnableForUnitTest();
|
||||
|
||||
if (isNotBlank(theValueSetUrl)) {
|
||||
return validateCodeInValueSet(theValidationSupportContext, theOptions, theValueSetUrl, theCodeSystem, theCode, theDisplay);
|
||||
return validateCodeInValueSet(theValidationSupportContext, theOptions, theValueSetUrl, theCodeSystemUrl, theCode, theDisplay);
|
||||
}
|
||||
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
Optional<FhirVersionIndependentConcept> codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new FhirVersionIndependentConcept(theCodeSystem, c.getCode())));
|
||||
txTemplate.setReadOnly(true);
|
||||
Optional<FhirVersionIndependentConcept> codeOpt = txTemplate.execute(tx -> findCode(theCodeSystemUrl, theCode).map(c -> {
|
||||
String codeSystemVersionId = getCurrentCodeSystemVersion(theCodeSystemUrl).myCodeSystemVersionId;
|
||||
return new FhirVersionIndependentConcept(theCodeSystemUrl, c.getCode(), c.getDisplay(), codeSystemVersionId);
|
||||
}));
|
||||
|
||||
if (codeOpt != null && codeOpt.isPresent()) {
|
||||
FhirVersionIndependentConcept code = codeOpt.get();
|
||||
if (!theOptions.isValidateDisplay() || (isNotBlank(code.getDisplay()) && isNotBlank(theDisplay) && code.getDisplay().equals(theDisplay))) {
|
||||
if (!theOptions.isValidateDisplay() || isBlank(code.getDisplay()) || isBlank(theDisplay) || code.getDisplay().equals(theDisplay)) {
|
||||
return new CodeValidationResult()
|
||||
.setCode(code.getCode())
|
||||
.setDisplay(code.getDisplay());
|
||||
} else {
|
||||
return createFailureCodeValidationResult(theCodeSystem, theCode, code.getSystemVersion(), " - Concept Display \"" + code.getDisplay() + "\" does not match expected \"" + code.getDisplay() + "\"").setDisplay(code.getDisplay());
|
||||
String messageAppend = createMessageAppendForDisplayMismatch(theCodeSystemUrl, theDisplay, code.getDisplay());
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode, code.getSystemVersion(), messageAppend).setDisplay(code.getDisplay());
|
||||
}
|
||||
}
|
||||
|
||||
return createFailureCodeValidationResult(theCodeSystem, theCode, null, " - Code can not be found in CodeSystem");
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode, null, createMessageAppendForCodeNotFoundInCodeSystem(theCodeSystemUrl));
|
||||
}
|
||||
|
||||
IValidationSupport.CodeValidationResult validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theValidationOptions, String theValueSetUrl, String theCodeSystem, String theCode, String theDisplay) {
|
||||
|
@ -2345,7 +2303,7 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
|
||||
// Check if someone is accidentally using a VS url where it should be a CS URL
|
||||
if (retVal != null && retVal.getCode() == null && theCodeSystem != null) {
|
||||
if (retVal != null && retVal.getCode() == null && theCodeSystem != null && myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU2)) {
|
||||
if (isValueSetSupported(theValidationSupportContext, theCodeSystem)) {
|
||||
if (!isCodeSystemSupported(theValidationSupportContext, theCodeSystem)) {
|
||||
String newMessage = "Unable to validate code " + theCodeSystem + "#" + theCode + " - Supplied system URL is a ValueSet URL and not a CodeSystem URL, check if it is correct: " + theCodeSystem;
|
||||
|
@ -2358,12 +2316,6 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaseResource fetchCodeSystem(String theSystem) {
|
||||
IValidationSupport jpaValidationSupport = provideJpaValidationSupport();
|
||||
return jpaValidationSupport.fetchCodeSystem(theSystem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeSystem fetchCanonicalCodeSystemFromCompleteContext(String theSystem) {
|
||||
IValidationSupport validationSupport = provideValidationSupport();
|
||||
|
@ -2494,69 +2446,6 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
return new FhirVersionIndependentConcept(system, code, null, systemVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CodeValidationResult codeSystemValidateCode(IIdType theCodeSystemId, String theCodeSystemUrl, String theVersion, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept) {
|
||||
|
||||
CodeableConcept codeableConcept = myVersionCanonicalizer.codeableConceptToCanonical(theCodeableConcept);
|
||||
boolean haveCodeableConcept = codeableConcept != null && codeableConcept.getCoding().size() > 0;
|
||||
|
||||
Coding coding = myVersionCanonicalizer.codingToCanonical((IBaseCoding) theCoding);
|
||||
boolean haveCoding = coding != null && !coding.isEmpty();
|
||||
|
||||
boolean haveCode = theCode != null && !theCode.isEmpty();
|
||||
|
||||
if (!haveCodeableConcept && !haveCoding && !haveCode) {
|
||||
throw new InvalidRequestException(Msg.code(906) + "No code, coding, or codeableConcept provided to validate.");
|
||||
}
|
||||
if (!LogicUtil.multiXor(haveCodeableConcept, haveCoding, haveCode)) {
|
||||
throw new InvalidRequestException(Msg.code(907) + "$validate-code can only validate (code) OR (coding) OR (codeableConcept)");
|
||||
}
|
||||
|
||||
boolean haveIdentifierParam = isNotBlank(theCodeSystemUrl);
|
||||
String codeSystemUrl;
|
||||
if (theCodeSystemId != null) {
|
||||
IBaseResource codeSystem = myDaoRegistry.getResourceDao("CodeSystem").read(theCodeSystemId);
|
||||
codeSystemUrl = CommonCodeSystemsTerminologyService.getCodeSystemUrl(codeSystem);
|
||||
} else if (haveIdentifierParam) {
|
||||
codeSystemUrl = theCodeSystemUrl;
|
||||
} else {
|
||||
throw new InvalidRequestException(Msg.code(908) + "Either CodeSystem ID or CodeSystem identifier must be provided. Unable to validate.");
|
||||
}
|
||||
|
||||
|
||||
String code = theCode;
|
||||
String display = theDisplay;
|
||||
|
||||
if (haveCodeableConcept) {
|
||||
for (int i = 0; i < codeableConcept.getCoding().size(); i++) {
|
||||
Coding nextCoding = codeableConcept.getCoding().get(i);
|
||||
if (nextCoding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(nextCoding.getSystem())) {
|
||||
throw new InvalidRequestException(Msg.code(909) + "Coding.system '" + nextCoding.getSystem() + "' does not equal with CodeSystem.url '" + theCodeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = nextCoding.getSystem();
|
||||
}
|
||||
code = nextCoding.getCode();
|
||||
display = nextCoding.getDisplay();
|
||||
CodeValidationResult nextValidation = codeSystemValidateCode(codeSystemUrl, theVersion, code, display);
|
||||
if (nextValidation.isOk() || i == codeableConcept.getCoding().size() - 1) {
|
||||
return nextValidation;
|
||||
}
|
||||
}
|
||||
} else if (haveCoding) {
|
||||
if (coding.hasSystem()) {
|
||||
if (!codeSystemUrl.equalsIgnoreCase(coding.getSystem())) {
|
||||
throw new InvalidRequestException(Msg.code(910) + "Coding.system '" + coding.getSystem() + "' does not equal with CodeSystem.url '" + theCodeSystemUrl + "'. Unable to validate.");
|
||||
}
|
||||
codeSystemUrl = coding.getSystem();
|
||||
}
|
||||
code = coding.getCode();
|
||||
display = coding.getDisplay();
|
||||
}
|
||||
|
||||
return codeSystemValidateCode(codeSystemUrl, theVersion, code, display);
|
||||
}
|
||||
|
||||
/**
|
||||
* When the search is for unversioned loinc system it uses the forcedId to obtain the current
|
||||
|
@ -2582,60 +2471,14 @@ public class TermReadSvcImpl implements ITermReadSvc {
|
|||
return Optional.of(termValueSetList.get(0));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private CodeValidationResult codeSystemValidateCode(String theCodeSystemUrl, String theCodeSystemVersion, String theCode, String theDisplay) {
|
||||
@Nonnull
|
||||
private static String createMessageAppendForDisplayMismatch(String theCodeSystemUrl, String theDisplay, String theExpectedDisplay) {
|
||||
return " - Concept Display \"" + theDisplay + "\" does not match expected \"" + theExpectedDisplay + "\" for CodeSystem: " + theCodeSystemUrl;
|
||||
}
|
||||
|
||||
CriteriaBuilder criteriaBuilder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<TermConcept> query = criteriaBuilder.createQuery(TermConcept.class);
|
||||
Root<TermConcept> root = query.from(TermConcept.class);
|
||||
|
||||
Fetch<TermCodeSystemVersion, TermConcept> systemVersionFetch = root.fetch("myCodeSystem", JoinType.INNER);
|
||||
Join<TermCodeSystemVersion, TermConcept> systemVersionJoin = (Join<TermCodeSystemVersion, TermConcept>) systemVersionFetch;
|
||||
Fetch<TermCodeSystem, TermCodeSystemVersion> systemFetch = systemVersionFetch.fetch("myCodeSystem", JoinType.INNER);
|
||||
Join<TermCodeSystem, TermCodeSystemVersion> systemJoin = (Join<TermCodeSystem, TermCodeSystemVersion>) systemFetch;
|
||||
|
||||
ArrayList<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
if (isNotBlank(theCode)) {
|
||||
predicates.add(criteriaBuilder.equal(root.get("myCode"), theCode));
|
||||
}
|
||||
|
||||
if (isNoneBlank(theCodeSystemUrl)) {
|
||||
predicates.add(criteriaBuilder.equal(systemJoin.get("myCodeSystemUri"), theCodeSystemUrl));
|
||||
}
|
||||
|
||||
// for loinc CodeSystem last version is not necessarily the current anymore, so if no version is present
|
||||
// we need to query for the current, which is that which version is null
|
||||
if (isNoneBlank(theCodeSystemVersion)) {
|
||||
predicates.add(criteriaBuilder.equal(systemVersionJoin.get("myCodeSystemVersionId"), theCodeSystemVersion));
|
||||
} else {
|
||||
if (theCodeSystemUrl.toLowerCase(Locale.ROOT).contains(LOINC_LOW)) {
|
||||
predicates.add(criteriaBuilder.isNull(systemVersionJoin.get("myCodeSystemVersionId")));
|
||||
} else {
|
||||
query.orderBy(criteriaBuilder.desc(root.get("myUpdated")));
|
||||
}
|
||||
}
|
||||
|
||||
Predicate outerPredicate = criteriaBuilder.and(predicates.toArray(new Predicate[0]));
|
||||
query.where(outerPredicate);
|
||||
|
||||
final TypedQuery<TermConcept> typedQuery = myEntityManager.createQuery(query.select(root));
|
||||
org.hibernate.query.Query<TermConcept> hibernateQuery = (org.hibernate.query.Query<TermConcept>) typedQuery;
|
||||
hibernateQuery.setFetchSize(SINGLE_FETCH_SIZE);
|
||||
List<TermConcept> resultsList = hibernateQuery.getResultList();
|
||||
|
||||
if (!resultsList.isEmpty()) {
|
||||
TermConcept concept = resultsList.get(0);
|
||||
|
||||
if (isNotBlank(theDisplay) && !theDisplay.equals(concept.getDisplay())) {
|
||||
String message = "Concept Display \"" + theDisplay + "\" does not match expected \"" + concept.getDisplay() + "\" for CodeSystem: " + theCodeSystemUrl;
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode, theCodeSystemVersion, message);
|
||||
}
|
||||
|
||||
return new CodeValidationResult().setCode(concept.getCode()).setDisplay(concept.getDisplay());
|
||||
}
|
||||
|
||||
return createFailureCodeValidationResult(theCodeSystemUrl, theCode, theCodeSystemVersion, " - Code is not found in CodeSystem: " + theCodeSystemUrl);
|
||||
@Nonnull
|
||||
private static String createMessageAppendForCodeNotFoundInCodeSystem(String theCodeSystemUrl) {
|
||||
return " - Code is not found in CodeSystem: " + theCodeSystemUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,7 +26,6 @@ import ca.uhn.fhir.jpa.entity.TermConcept;
|
|||
import ca.uhn.fhir.jpa.model.sched.HapiJob;
|
||||
import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
|
||||
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReindexingSvc;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
|
@ -71,7 +70,7 @@ public class TermReindexingSvcImpl implements ITermReindexingSvc {
|
|||
|
||||
@Override
|
||||
public void processReindexing() {
|
||||
if (myDeferredStorageSvc.isStorageQueueEmpty() == false && !ourForceSaveDeferredAlwaysForUnitTest) {
|
||||
if (myDeferredStorageSvc.isStorageQueueEmpty(true) == false && !ourForceSaveDeferredAlwaysForUnitTest) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,20 @@ public interface ITermDeferredStorageSvc {
|
|||
|
||||
void saveDeferred();
|
||||
|
||||
boolean isStorageQueueEmpty();
|
||||
/**
|
||||
* @deprecated Use {@link #isStorageQueueEmpty(boolean)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean isStorageQueueEmpty() {
|
||||
return isStorageQueueEmpty(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* If you are calling this in a loop or something similar, consider the impact of
|
||||
* setting {@literal theIncludeExecutingJobs} to true. When that parameter is set
|
||||
* to true, each call to this method results in a database lookup!
|
||||
*/
|
||||
boolean isStorageQueueEmpty(boolean theIncludeExecutingJobs);
|
||||
|
||||
/**
|
||||
* This is mostly for unit tests - we can disable processing of deferred concepts
|
||||
|
|
|
@ -17,10 +17,10 @@ import org.hl7.fhir.instance.model.api.IIdType;
|
|||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
@ -98,11 +98,6 @@ public interface ITermReadSvc extends IValidationSupport {
|
|||
|
||||
void preExpandDeferredValueSetsToTerminologyTables();
|
||||
|
||||
/**
|
||||
* Version independent
|
||||
*/
|
||||
CodeValidationResult validateCode(ConceptValidationOptions theOptions, IIdType theValueSetId, String theValueSetUrl, String theSystem, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept);
|
||||
|
||||
/**
|
||||
* Version independent
|
||||
*/
|
||||
|
@ -116,11 +111,6 @@ public interface ITermReadSvc extends IValidationSupport {
|
|||
*/
|
||||
boolean isValueSetPreExpandedForCodeValidation(IBaseResource theValueSet);
|
||||
|
||||
/**
|
||||
* Version independent
|
||||
*/
|
||||
CodeValidationResult codeSystemValidateCode(IIdType theCodeSystemId, String theValueSetUrl, String theVersion, String theCode, String theDisplay, IBaseDatatype theCoding, IBaseDatatype theCodeableConcept);
|
||||
|
||||
String invalidatePreCalculatedExpansion(IIdType theValueSetId, RequestDetails theRequestDetails);
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,15 +31,21 @@ public class LogicUtil {
|
|||
private LogicUtil() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true IF and ONLY IF exactly 1 of the provided boolean(s) is true
|
||||
*/
|
||||
public static boolean multiXor(boolean... theValues) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < theValues.length; i++) {
|
||||
if (theValues[i]) {
|
||||
count++;
|
||||
boolean foundOne = false;
|
||||
for (boolean next : theValues) {
|
||||
if (next) {
|
||||
if (foundOne) {
|
||||
return false;
|
||||
}
|
||||
foundOne = true;
|
||||
}
|
||||
}
|
||||
return count == 1;
|
||||
return foundOne;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -44,6 +44,12 @@ public class BaseCqlR4Test extends BaseJpaR4Test implements CqlProviderTestBase
|
|||
@RegisterExtension
|
||||
protected PartitionHelper myPartitionHelper;
|
||||
|
||||
// FIXME: restore?
|
||||
// @Override
|
||||
// public void beforeResetInterceptors() {
|
||||
// myInterceptorRegistry.unregisterInterceptorsIf(t->!(t instanceof PartitionHelper.MyTestInterceptor));
|
||||
// }
|
||||
|
||||
@Autowired
|
||||
protected
|
||||
DaoRegistry myDaoRegistry;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -87,15 +87,15 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-api</artifactId>
|
||||
<artifactId>websocket-jetty-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-client</artifactId>
|
||||
<artifactId>websocket-core-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||
<artifactId>websocket-server</artifactId>
|
||||
<artifactId>websocket-jetty-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -165,7 +165,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
|
|||
protected ISearchParamRegistry mySearchParamRegistry;
|
||||
@Autowired
|
||||
@Qualifier("myValueSetDaoR4")
|
||||
protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao;
|
||||
protected IFhirResourceDaoValueSet<ValueSet> myValueSetDao;
|
||||
@Autowired
|
||||
protected ITermReadSvc myTermSvc;
|
||||
@Autowired
|
||||
|
|
|
@ -61,14 +61,14 @@ public class FhirResourceDaoR4TerminologyElasticsearchIT extends BaseJpaTest {
|
|||
protected DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
@Qualifier("myCodeSystemDaoR4")
|
||||
protected IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
|
||||
protected IFhirResourceDaoCodeSystem<CodeSystem> myCodeSystemDao;
|
||||
@Autowired
|
||||
protected IResourceTableDao myResourceTableDao;
|
||||
@Autowired
|
||||
protected ITermCodeSystemStorageSvc myTermCodeSystemStorageSvc;
|
||||
@Autowired
|
||||
@Qualifier("myValueSetDaoR4")
|
||||
protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao;
|
||||
protected IFhirResourceDaoValueSet<ValueSet> myValueSetDao;
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
protected ServletRequestDetails mySrd;
|
||||
@Autowired
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.config.TestR4ConfigWithElasticHSearch;
|
||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.test.utilities.docker.RequiresDocker;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -89,7 +90,7 @@ public class ResourceProviderR4ElasticTest extends BaseResourceProviderR4Test {
|
|||
createObservationWithCode(mean_blood_pressure);
|
||||
|
||||
// when
|
||||
HttpGet expandQuery = new HttpGet(BaseResourceProviderR4Test.ourServerBase + "/ValueSet/$expand?contextDirection=existing&context=Observation.code:text&filter=pressure");
|
||||
HttpGet expandQuery = new HttpGet(ourServerBase + "/ValueSet/$expand?contextDirection=existing&context=Observation.code:text&filter=pressure");
|
||||
try (CloseableHttpResponse response = BaseResourceProviderR4Test.ourHttpClient.execute(expandQuery)) {
|
||||
|
||||
// then
|
||||
|
@ -166,7 +167,7 @@ public class ResourceProviderR4ElasticTest extends BaseResourceProviderR4Test {
|
|||
Coding blood_count = new Coding("http://loinc.org", "789-8", "Erythrocytes in Blood by Automated count for code: " + (index + 1));
|
||||
createObservationWithCode(blood_count);
|
||||
});
|
||||
HttpGet countQuery = new HttpGet(BaseResourceProviderR4Test.ourServerBase + "/Observation?code=789-8&_count=5&_total=accurate");
|
||||
HttpGet countQuery = new HttpGet(ourServerBase + "/Observation?code=789-8&_count=5&_total=accurate");
|
||||
myCaptureQueriesListener.clear();
|
||||
try (CloseableHttpResponse response = BaseResourceProviderR4Test.ourHttpClient.execute(countQuery)) {
|
||||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||
|
@ -187,7 +188,7 @@ public class ResourceProviderR4ElasticTest extends BaseResourceProviderR4Test {
|
|||
Coding blood_count = new Coding("http://loinc.org", "789-8", "Erythrocytes in Blood by Automated count for code: " + (index + 1));
|
||||
createObservationWithCode(blood_count);
|
||||
});
|
||||
HttpGet countQuery = new HttpGet(BaseResourceProviderR4Test.ourServerBase + "/Observation?code=789-8&_count=0");
|
||||
HttpGet countQuery = new HttpGet(ourServerBase + "/Observation?code=789-8&_count=0");
|
||||
myCaptureQueriesListener.clear();
|
||||
try (CloseableHttpResponse response = BaseResourceProviderR4Test.ourHttpClient.execute(countQuery)) {
|
||||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||
|
|
|
@ -30,8 +30,6 @@ import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
|||
import ca.uhn.fhir.test.utilities.docker.RequiresDocker;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
@ -77,14 +75,14 @@ public class ValueSetExpansionR4ElasticsearchIT extends BaseJpaTest {
|
|||
protected DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
@Qualifier("myCodeSystemDaoR4")
|
||||
protected IFhirResourceDaoCodeSystem<CodeSystem, Coding, CodeableConcept> myCodeSystemDao;
|
||||
protected IFhirResourceDaoCodeSystem<CodeSystem> myCodeSystemDao;
|
||||
@Autowired
|
||||
protected IResourceTableDao myResourceTableDao;
|
||||
@Autowired
|
||||
protected ITermCodeSystemStorageSvc myTermCodeSystemStorageSvc;
|
||||
@Autowired
|
||||
@Qualifier("myValueSetDaoR4")
|
||||
protected IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> myValueSetDao;
|
||||
protected IFhirResourceDaoValueSet<ValueSet> myValueSetDao;
|
||||
@Autowired
|
||||
protected ITermReadSvc myTermSvc;
|
||||
@Autowired
|
||||
|
@ -250,7 +248,7 @@ public class ValueSetExpansionR4ElasticsearchIT extends BaseJpaTest {
|
|||
new SystemRequestDetails(), Collections.singletonList(valueSet), Collections.emptyList());
|
||||
|
||||
myTerminologyDeferredStorageSvc.saveAllDeferred();
|
||||
await().atMost(10, SECONDS).until(myTerminologyDeferredStorageSvc::isStorageQueueEmpty);
|
||||
await().atMost(10, SECONDS).until(() -> myTerminologyDeferredStorageSvc.isStorageQueueEmpty(true));
|
||||
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.0-PRE3-SNAPSHOT</version>
|
||||
<version>6.3.0-PRE4-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -63,12 +63,6 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-test-utilities</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue