Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2018-05-15 11:47:46 -04:00
commit 6f76852e93
75 changed files with 4463 additions and 4191 deletions

View File

@ -181,8 +181,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>

View File

@ -60,7 +60,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu3 {
@Bean()
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean retVal = entityManagerFactory();
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
retVal.setPersistenceUnitName("HAPI_PU");
retVal.setDataSource(dataSource());
retVal.setJpaProperties(jpaProperties());

View File

@ -11,7 +11,7 @@
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>3.4.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>hapi-fhir-jpaserver-dynamic</artifactId>

View File

@ -100,8 +100,8 @@
<artifactId>javax.mail-api</artifactId>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
@ -140,6 +140,7 @@
<ignoredResourcePattern>changelog.txt</ignoredResourcePattern>
<ignoredResource>javac.bat</ignoredResource>
<ignoredResource>about.html</ignoredResource>
<ignoredResource>changelog.xml</ignoredResource>
</ignoredResourcePatterns>
</configuration>
</plugin>

View File

@ -45,27 +45,14 @@
<!-- Only required for Schematron Validator Support -->
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<optional>true</optional>
<exclusions><!--
<exclusion>
<artifactId>Saxon-HE</artifactId>
<groupId>net.sf.saxon</groupId>
</exclusion>-->
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<!-- Guava brings in a newer replacement for this dependency called com.google.code.findbugs:jsr305 -->
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId>

View File

@ -42,9 +42,9 @@ import ca.uhn.fhir.validation.schematron.SchematronProvider;
*/
public class FhirValidator {
private static final String I18N_KEY_NO_PHLOC_ERROR = FhirValidator.class.getName() + ".noPhlocError";
private static final String I18N_KEY_NO_PH_ERROR = FhirValidator.class.getName() + ".noPhError";
private static volatile Boolean ourPhlocPresentOnClasspath;
private static volatile Boolean ourPhPresentOnClasspath;
private final FhirContext myContext;
private List<IValidatorModule> myValidators = new ArrayList<IValidatorModule>();
@ -54,8 +54,8 @@ public class FhirValidator {
public FhirValidator(FhirContext theFhirContext) {
myContext = theFhirContext;
if (ourPhlocPresentOnClasspath == null) {
ourPhlocPresentOnClasspath = SchematronProvider.isSchematronAvailable(theFhirContext);
if (ourPhPresentOnClasspath == null) {
ourPhPresentOnClasspath = SchematronProvider.isSchematronAvailable(theFhirContext);
}
}
@ -96,9 +96,10 @@ public class FhirValidator {
* Should the validator validate the resource against the base schema (the schema provided with the FHIR distribution itself)
*/
public synchronized boolean isValidateAgainstStandardSchematron() {
if (!ourPhlocPresentOnClasspath) {
return false; // No need to ask since we dont have Phloc. Also Class.forname will complain
// about missing phloc import.
if (!ourPhPresentOnClasspath) {
// No need to ask since we dont have Ph-Schematron. Also Class.forname will complain
// about missing ph-schematron import.
return false;
}
Class<? extends IValidatorModule> cls = SchematronProvider.getSchematronValidatorClass();
return haveValidatorOfType(cls);
@ -135,8 +136,11 @@ public class FhirValidator {
* @return Returns a referens to <code>this<code> for method chaining
*/
public synchronized FhirValidator setValidateAgainstStandardSchematron(boolean theValidateAgainstStandardSchematron) {
if (theValidateAgainstStandardSchematron && !ourPhlocPresentOnClasspath) {
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_ERROR));
if (theValidateAgainstStandardSchematron && !ourPhPresentOnClasspath) {
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_KEY_NO_PH_ERROR));
}
if (!theValidateAgainstStandardSchematron && !ourPhPresentOnClasspath) {
return this;
}
Class<? extends IValidatorModule> cls = SchematronProvider.getSchematronValidatorClass();
IValidatorModule instance = SchematronProvider.getSchematronValidatorInstance(myContext);
@ -163,7 +167,7 @@ public class FhirValidator {
private void applyDefaultValidators() {
if (myValidators.isEmpty()) {
setValidateAgainstStandardSchema(true);
if (ourPhlocPresentOnClasspath) {
if (ourPhPresentOnClasspath) {
setValidateAgainstStandardSchematron(true);
}
}

View File

@ -20,28 +20,28 @@ package ca.uhn.fhir.validation.schematron;
* #L%
*/
import java.io.InputStream;
import java.io.StringReader;
import java.util.*;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.oclc.purl.dsdl.svrl.SchematronOutputType;
import com.phloc.commons.error.IResourceError;
import com.phloc.commons.error.IResourceErrorGroup;
import com.phloc.schematron.ISchematronResource;
import com.phloc.schematron.SchematronHelper;
import com.phloc.schematron.xslt.SchematronResourceSCH;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.validation.*;
import com.helger.commons.error.IError;
import com.helger.commons.error.list.IErrorList;
import com.helger.schematron.ISchematronResource;
import com.helger.schematron.SchematronHelper;
import com.helger.schematron.xslt.SchematronResourceSCH;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.oclc.purl.dsdl.svrl.SchematronOutputType;
import javax.xml.transform.stream.StreamSource;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* This class is only used using reflection from {@link SchematronProvider} in order
@ -81,27 +81,21 @@ public class SchematronBaseValidator implements IValidatorModule {
return;
}
IResourceErrorGroup errors = SchematronHelper.convertToResourceErrorGroup(results, theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName());
IErrorList errors = SchematronHelper.convertToErrorList(results, theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName());
if (errors.getAllErrors().containsOnlySuccess()) {
return;
}
for (IResourceError next : errors.getAllErrors().getAllResourceErrors()) {
for (IError next : errors) {
ResultSeverityEnum severity;
switch (next.getErrorLevel()) {
case ERROR:
if (next.isFailure()) {
severity = ResultSeverityEnum.ERROR;
break;
case FATAL_ERROR:
} else if (next.isError()) {
severity = ResultSeverityEnum.FATAL;
break;
case WARN:
} else if (next.isNoError()) {
severity = ResultSeverityEnum.WARNING;
break;
case INFO:
case SUCCESS:
default:
} else {
continue;
}
@ -109,9 +103,9 @@ public class SchematronBaseValidator implements IValidatorModule {
SingleValidationMessage message = new SingleValidationMessage();
message.setMessage(details);
message.setLocationLine(next.getLocation().getLineNumber());
message.setLocationCol(next.getLocation().getColumnNumber());
message.setLocationString(next.getLocation().getAsString());
message.setLocationLine(next.getErrorLocation().getLineNumber());
message.setLocationCol(next.getErrorLocation().getColumnNumber());
message.setLocationString(next.getErrorLocation().getAsString());
message.setSeverity(severity);
theCtx.addValidationMessage(message);
}

View File

@ -30,16 +30,16 @@ import ca.uhn.fhir.validation.IValidatorModule;
public class SchematronProvider {
private static final String I18N_KEY_NO_PHLOC_WARNING = FhirValidator.class.getName() + ".noPhlocWarningOnStartup";
private static final String I18N_KEY_NO_PH_WARNING = FhirValidator.class.getName() + ".noPhWarningOnStartup";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirValidator.class);
@CoverageIgnore
public static boolean isSchematronAvailable(FhirContext theFhirContext) {
try {
Class.forName("com.phloc.schematron.ISchematronResource");
Class.forName("com.helger.schematron.ISchematronResource");
return true;
} catch (ClassNotFoundException e) {
ourLog.info(theFhirContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_WARNING));
ourLog.info(theFhirContext.getLocalizer().getMessage(I18N_KEY_NO_PH_WARNING));
return false;
}
}

View File

@ -51,8 +51,8 @@ ca.uhn.fhir.rest.server.RestfulServer.unknownMethod=Invalid request: The FHIR en
ca.uhn.fhir.rest.server.RestfulServer.rootRequest=This is the base URL of FHIR server. Unable to handle this request, as it does not contain a resource type or operation name.
ca.uhn.fhir.rest.server.RestfulServer.rootRequest.multitenant=This is the base URL of a multitenant FHIR server. Unable to handle this request, as it does not contain a tenant ID.
ca.uhn.fhir.validation.ValidationContext.unableToDetermineEncoding=Unable to determine encoding (e.g. XML / JSON) on validation input. Is this a valid FHIR resource body?
ca.uhn.fhir.validation.FhirValidator.noPhlocWarningOnStartup=Phloc-schematron library not found on classpath, will not attempt to perform schematron validation
ca.uhn.fhir.validation.FhirValidator.noPhlocError=Phloc-schematron library not found on classpath, can not enable perform schematron validation
ca.uhn.fhir.validation.FhirValidator.noPhWarningOnStartup=Ph-schematron library not found on classpath, will not attempt to perform schematron validation
ca.uhn.fhir.validation.FhirValidator.noPhError=Ph-schematron library not found on classpath, can not enable perform schematron validation
ca.uhn.fhir.validation.ValidationResult.noIssuesDetected=No issues detected during validation
# JPA Messages

View File

@ -69,12 +69,6 @@
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-igpacks</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
@ -173,8 +167,8 @@
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>
@ -183,8 +177,8 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
</dependency>
<!--
@ -196,14 +190,11 @@
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>

View File

@ -24,7 +24,7 @@ import ca.uhn.fhir.util.VersionUtil;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import com.phloc.commons.io.file.FileUtils;
import com.helger.commons.io.file.FileHelper;
import org.apache.commons.cli.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
@ -60,7 +60,7 @@ public abstract class BaseApp {
System.out.println("------------------------------------------------------------");
System.out.println("\ud83d\udd25 " + ansi().bold() + " " + provideProductName() + ansi().boldOff() + " " + provideProductVersion() + " - Command Line Tool");
System.out.println("------------------------------------------------------------");
System.out.println("Max configured JVM memory (Xmx): " + FileUtils.getFileSizeDisplay(Runtime.getRuntime().maxMemory(), 1));
System.out.println("Max configured JVM memory (Xmx): " + FileHelper.getFileSizeDisplay(Runtime.getRuntime().maxMemory(), 1));
System.out.println("Detected Java version: " + System.getProperty("java.version"));
System.out.println("------------------------------------------------------------");
}
@ -233,10 +233,10 @@ public abstract class BaseApp {
} else {
System.exit(1);
}
} catch (Exception e) {
ourLog.error("Error during execution: ", e);
} catch (Throwable t) {
ourLog.error("Error during execution: ", t);
if ("true".equals(System.getProperty("test"))) {
throw new CommandFailureException("Error: " + e.toString(), e);
throw new CommandFailureException("Error: " + t.toString(), t);
} else {
System.exit(1);
}

View File

@ -30,7 +30,7 @@ public class CommandFailureException extends Error {
super(theMessage);
}
public CommandFailureException(String theString, Exception theCause) {
public CommandFailureException(String theString, Throwable theCause) {
super(theString, theCause);
}

View File

@ -27,8 +27,8 @@ import ca.uhn.fhir.parser.LenientErrorHandler;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.SingleValidationMessage;
import ca.uhn.fhir.validation.ValidationResult;
import com.helger.commons.io.file.FileHelper;
import com.google.common.base.Charsets;
import com.phloc.commons.io.file.FileUtils;
import org.apache.commons.cli.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.text.WordUtils;
@ -80,7 +80,8 @@ public class ValidateCommand extends BaseCommand {
addOptionalOption(retVal, "x", "xsd", false, "Validate using Schemas");
addOptionalOption(retVal, "s", "sch", false, "Validate using Schematrons");
addOptionalOption(retVal, "e", "encoding","encoding", "File encoding (default is UTF-8)");
return retVal;
return retVal;
}
private String loadFile(String theFileName) throws ParseException {
@ -119,7 +120,7 @@ public class ValidateCommand extends BaseCommand {
} catch (IOException e) {
throw new CommandFailureException(e);
}
ourLog.info("Fully read - Size is {}", FileUtils.getFileSizeDisplay(contents.length()));
ourLog.info("Fully read - Size is {}", FileHelper.getFileSizeDisplay(contents.length()));
}
ca.uhn.fhir.rest.api.EncodingEnum enc = ca.uhn.fhir.rest.api.EncodingEnum.detectEncodingNoDefault(defaultString(contents));

View File

@ -132,8 +132,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>

View File

@ -217,18 +217,18 @@
<artifactId>thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>
<groupId>net.sf.saxon</groupId>
</exclusion>
</exclusions>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>
<groupId>net.sf.saxon</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>

View File

@ -78,8 +78,8 @@
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>
@ -88,8 +88,8 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>

View File

@ -123,11 +123,6 @@
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.ttddyy</groupId>
<artifactId>datasource-proxy</artifactId>
@ -146,8 +141,8 @@
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
@ -157,8 +152,8 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>
@ -468,6 +463,11 @@
<artifactId>greenmail-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
@ -566,19 +566,9 @@
as JDK9 no longer includes them by default
-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb_api_version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>${jaxb_core_version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb_core_version}</version>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>${jaxb_runtime_version}</version>
</dependency>
</dependencies>
</plugin>

View File

@ -73,7 +73,10 @@ import org.hl7.fhir.r4.model.BaseResource;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.Reference;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
@ -100,7 +103,7 @@ import static org.apache.commons.lang3.StringUtils.*;
@SuppressWarnings("WeakerAccess")
@Repository
public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao, ApplicationContextAware {
public static final long INDEX_STATUS_INDEXED = 1L;
public static final long INDEX_STATUS_INDEXING_FAILED = 2L;
@ -186,9 +189,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
@Autowired
private PlatformTransactionManager myPlatformTransactionManager;
@Autowired
private List<IFhirResourceDao<?>> myResourceDaos;
private Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> myResourceTypeToDao;
@Autowired
private ISearchDao mySearchDao;
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
@ -200,6 +200,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
private ISearchResultDao mySearchResultDao;
@Autowired
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
private ApplicationContext myApplicationContext;
private Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> myResourceTypeToDao;
protected void clearRequestAsProcessingSubRequest(ServletRequestDetails theRequestDetails) {
if (theRequestDetails != null) {
@ -695,6 +697,29 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
return retVal;
}
@SuppressWarnings("unchecked")
public <R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType) {
if (myResourceTypeToDao == null) {
Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> theResourceTypeToDao = new HashMap<>();
Map<String, IFhirResourceDao> daos = myApplicationContext.getBeansOfType(IFhirResourceDao.class, false, false);
for (IFhirResourceDao<?> next : daos.values()) {
theResourceTypeToDao.put(next.getResourceType(), next);
}
if (this instanceof IFhirResourceDao<?>) {
IFhirResourceDao<?> thiz = (IFhirResourceDao<?>) this;
theResourceTypeToDao.put(thiz.getResourceType(), thiz);
}
myResourceTypeToDao = theResourceTypeToDao;
}
IFhirResourceDao<R> dao = (IFhirResourceDao<R>) myResourceTypeToDao.get(theType);
return dao;
}
protected Set<ResourceIndexedSearchParamCoords> extractSearchParamCoords(ResourceTable theEntity, IBaseResource theResource) {
return mySearchParamExtractor.extractSearchParamCoords(theEntity, theResource);
}
@ -896,6 +921,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
return myConfig;
}
@Override
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
myApplicationContext = theApplicationContext;
}
public void setConfig(DaoConfig theConfig) {
myConfig = theConfig;
}
@ -922,26 +952,6 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
}
}
@SuppressWarnings("unchecked")
public <R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType) {
if (myResourceTypeToDao == null) {
Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> theResourceTypeToDao = new HashMap<>();
for (IFhirResourceDao<?> next : myResourceDaos) {
theResourceTypeToDao.put(next.getResourceType(), next);
}
if (this instanceof IFhirResourceDao<?>) {
IFhirResourceDao<?> thiz = (IFhirResourceDao<?>) this;
theResourceTypeToDao.put(thiz.getResourceType(), thiz);
}
myResourceTypeToDao = theResourceTypeToDao;
}
IFhirResourceDao<R> dao = (IFhirResourceDao<R>) myResourceTypeToDao.get(theType);
return dao;
}
public IResourceIndexedCompositeStringUniqueDao getResourceIndexedCompositeStringUniqueDao() {
return myResourceIndexedCompositeStringUniqueDao;
}

View File

@ -159,7 +159,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
return doExpunge(null, null, null, theExpungeOptions);
}
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
@Transactional(propagation = Propagation.REQUIRED)
@Override
public Map<String, Long> getResourceCounts() {
Map<String, Long> retVal = new HashMap<>();
@ -172,7 +172,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
return retVal;
}
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
@Transactional(propagation = Propagation.SUPPORTS)
@Nullable
@Override
public Map<String, Long> getResourceCountsFromCache() {
@ -265,7 +265,7 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
}
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Transactional(propagation = Propagation.NEVER)
public Integer performReindexingPass(final Integer theCount) {
if (!myReindexLock.tryLock()) {
return null;

View File

@ -32,7 +32,10 @@ import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.PostConstruct;
@ -40,7 +43,7 @@ import java.util.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
public abstract class BaseSearchParamRegistry<SP extends IBaseResource> implements ISearchParamRegistry {
public abstract class BaseSearchParamRegistry<SP extends IBaseResource> implements ISearchParamRegistry, ApplicationContextAware {
private static final int MAX_MANAGED_PARAM_COUNT = 10000;
private static final Logger ourLog = LoggerFactory.getLogger(BaseSearchParamRegistry.class);
@ -49,12 +52,12 @@ public abstract class BaseSearchParamRegistry<SP extends IBaseResource> implemen
private volatile Map<String, Map<Set<String>, List<JpaRuntimeSearchParam>>> myActiveParamNamesToUniqueSearchParams = Collections.emptyMap();
@Autowired
private FhirContext myCtx;
@Autowired
private Collection<IFhirResourceDao<?>> myDaos;
private Collection<IFhirResourceDao<?>> myResourceDaos;
private volatile Map<String, Map<String, RuntimeSearchParam>> myActiveSearchParams;
@Autowired
private DaoConfig myDaoConfig;
private volatile long myLastRefresh;
private ApplicationContext myApplicationContext;
public BaseSearchParamRegistry() {
super();
@ -212,7 +215,13 @@ public abstract class BaseSearchParamRegistry<SP extends IBaseResource> implemen
public void postConstruct() {
Map<String, Map<String, RuntimeSearchParam>> resourceNameToSearchParams = new HashMap<>();
for (IFhirResourceDao<?> nextDao : myDaos) {
myResourceDaos = new ArrayList<>();
Map<String, IFhirResourceDao> daos = myApplicationContext.getBeansOfType(IFhirResourceDao.class, false, false);
for (IFhirResourceDao next : daos.values()) {
myResourceDaos.add(next);
}
for (IFhirResourceDao<?> nextDao : myResourceDaos) {
RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(nextDao.getResourceType());
String nextResourceName = nextResDef.getName();
HashMap<String, RuntimeSearchParam> nameToParam = new HashMap<>();
@ -321,6 +330,11 @@ public abstract class BaseSearchParamRegistry<SP extends IBaseResource> implemen
refreshCacheIfNecessary();
}
@Override
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
myApplicationContext = theApplicationContext;
}
protected abstract RuntimeSearchParam toRuntimeSp(SP theNextSp);

View File

@ -33,6 +33,8 @@ import ca.uhn.fhir.model.primitive.CodeDt;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
@ -58,6 +60,7 @@ public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2<Se
*/
@Override
@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
@Transactional(propagation = Propagation.NEVER)
public void performReindexingPass() {
if (getConfig().isSchedulingDisabled()) {
return;

View File

@ -68,6 +68,7 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.TypedQuery;
@ -103,15 +104,20 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
Bundle subRequestBundle = new Bundle();
subRequestBundle.setType(BundleTypeEnum.TRANSACTION);
subRequestBundle.addEntry(nextRequestEntry);
Bundle subResponseBundle = transaction((ServletRequestDetails) theRequestDetails, subRequestBundle, "Batch sub-request");
return subResponseBundle;
return transaction((ServletRequestDetails) theRequestDetails, subRequestBundle, "Batch sub-request");
}
};
BaseServerResponseException caughtEx;
try {
Bundle nextResponseBundle = txTemplate.execute(callback);
Bundle nextResponseBundle;
if (nextRequestEntry.getRequest().getMethodElement().getValueAsEnum() == HTTPVerbEnum.GET) {
// Don't process GETs in a transaction because they'll
// create their own
nextResponseBundle = callback.doInTransaction(null);
} else {
nextResponseBundle = txTemplate.execute(callback);
}
caughtEx = null;
Entry subResponseEntry = nextResponseBundle.getEntry().get(0);
@ -156,13 +162,17 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
return batch(theRequestDetails, theRequest);
}
if (transactionType == null) {
String message = "Transactiion Bundle did not specify valid Bundle.type, assuming " + BundleTypeEnum.TRANSACTION.getCode();
return doTransaction(theRequestDetails, theRequest, theActionName, transactionType);
}
private Bundle doTransaction(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, BundleTypeEnum theTransactionType) {
if (theTransactionType == null) {
String message = "Transaction Bundle did not specify valid Bundle.type, assuming " + BundleTypeEnum.TRANSACTION.getCode();
ourLog.warn(message);
transactionType = BundleTypeEnum.TRANSACTION;
theTransactionType = BundleTypeEnum.TRANSACTION;
}
if (transactionType != BundleTypeEnum.TRANSACTION) {
throw new InvalidRequestException("Unable to process transaction where incoming Bundle.type = " + transactionType.getCode());
if (theTransactionType != BundleTypeEnum.TRANSACTION) {
throw new InvalidRequestException("Unable to process transaction where incoming Bundle.type = " + theTransactionType.getCode());
}
ourLog.info("Beginning {} with {} resources", theActionName, theRequest.getEntry().size());
@ -186,7 +196,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
*/
Bundle response = new Bundle();
List<Entry> getEntries = new ArrayList<Entry>();
IdentityHashMap<Entry, Integer> originalRequestOrder = new IdentityHashMap<Bundle.Entry, Integer>();
IdentityHashMap<Entry, Integer> originalRequestOrder = new IdentityHashMap<Entry, Integer>();
for (int i = 0; i < theRequest.getEntry().size(); i++) {
originalRequestOrder.put(theRequest.getEntry().get(i), i);
response.addEntry();
@ -203,225 +213,13 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
Set<ResourceTable> updatedEntities = new HashSet<>();
/*
* Loop through the request and process any entries of type
* PUT, POST or DELETE
* Handle: GET/PUT/POST
*/
for (int i = 0; i < theRequest.getEntry().size(); i++) {
if (i % 100 == 0) {
ourLog.debug("Processed {} non-GET entries out of {}", i, theRequest.getEntry().size());
}
Entry nextReqEntry = theRequest.getEntry().get(i);
IResource res = nextReqEntry.getResource();
IdDt nextResourceId = null;
if (res != null) {
nextResourceId = res.getId();
if (!nextResourceId.hasIdPart()) {
if (isNotBlank(nextReqEntry.getFullUrl())) {
nextResourceId = new IdDt(nextReqEntry.getFullUrl());
}
}
if (nextResourceId.hasIdPart() && nextResourceId.getIdPart().matches("[a-zA-Z]+\\:.*") && !isPlaceholder(nextResourceId)) {
throw new InvalidRequestException("Invalid placeholder ID found: " + nextResourceId.getIdPart() + " - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'");
}
if (nextResourceId.hasIdPart() && !nextResourceId.hasResourceType() && !isPlaceholder(nextResourceId)) {
nextResourceId = new IdDt(toResourceName(res.getClass()), nextResourceId.getIdPart());
res.setId(nextResourceId);
}
/*
* Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
*/
if (isPlaceholder(nextResourceId)) {
if (!allIds.add(nextResourceId)) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextResourceId));
}
} else if (nextResourceId.hasResourceType() && nextResourceId.hasIdPart()) {
IdDt nextId = nextResourceId.toUnqualifiedVersionless();
if (!allIds.add(nextId)) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextId));
}
}
}
HTTPVerbEnum verb = nextReqEntry.getRequest().getMethodElement().getValueAsEnum();
if (verb == null) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionEntryHasInvalidVerb", nextReqEntry.getRequest().getMethod()));
}
String resourceType = res != null ? getContext().getResourceDefinition(res).getName() : null;
Entry nextRespEntry = response.getEntry().get(originalRequestOrder.get(nextReqEntry));
switch (verb) {
case POST: {
// CREATE
@SuppressWarnings("rawtypes")
IFhirResourceDao resourceDao = getDaoOrThrowException(res.getClass());
res.setId((String) null);
DaoMethodOutcome outcome;
outcome = resourceDao.create(res, nextReqEntry.getRequest().getIfNoneExist(), false, theRequestDetails);
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
entriesToProcess.put(nextRespEntry, outcome.getEntity());
if (outcome.getCreated() == false) {
nonUpdatedEntities.add(outcome.getEntity());
}
break;
}
case DELETE: {
// DELETE
String url = extractTransactionUrlOrThrowException(nextReqEntry, verb);
UrlParts parts = UrlUtil.parseUrl(url);
ca.uhn.fhir.jpa.dao.IFhirResourceDao<? extends IBaseResource> dao = toDao(parts, verb.getCode(), url);
int status = Constants.STATUS_HTTP_204_NO_CONTENT;
if (parts.getResourceId() != null) {
DaoMethodOutcome outcome = dao.delete(new IdDt(parts.getResourceType(), parts.getResourceId()), deleteConflicts, theRequestDetails);
if (outcome.getEntity() != null) {
deletedResources.add(outcome.getId().toUnqualifiedVersionless());
entriesToProcess.put(nextRespEntry, outcome.getEntity());
}
} else {
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams(), deleteConflicts, theRequestDetails);
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
for (ResourceTable deleted : allDeleted) {
deletedResources.add(deleted.getIdDt().toUnqualifiedVersionless());
}
if (allDeleted.isEmpty()) {
status = Constants.STATUS_HTTP_404_NOT_FOUND;
}
}
nextRespEntry.getResponse().setStatus(toStatusString(status));
break;
}
case PUT: {
// UPDATE
@SuppressWarnings("rawtypes")
IFhirResourceDao resourceDao = getDaoOrThrowException(res.getClass());
DaoMethodOutcome outcome;
String url = extractTransactionUrlOrThrowException(nextReqEntry, verb);
UrlParts parts = UrlUtil.parseUrl(url);
if (isNotBlank(parts.getResourceId())) {
res.setId(new IdDt(parts.getResourceType(), parts.getResourceId()));
outcome = resourceDao.update(res, null, false, theRequestDetails);
} else {
res.setId((String) null);
outcome = resourceDao.update(res, parts.getResourceType() + '?' + parts.getParams(), false, theRequestDetails);
}
if (outcome.getCreated() == Boolean.FALSE) {
updatedEntities.add(outcome.getEntity());
}
handleTransactionCreateOrUpdateOutcome(idSubstitutions, idToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
entriesToProcess.put(nextRespEntry, outcome.getEntity());
break;
}
case GET:
break;
}
}
/*
* Make sure that there are no conflicts from deletions. E.g. we can't delete something
* if something else has a reference to it.. Unless the thing that has a reference to it
* was also deleted as a part of this transaction, which is why we check this now at the
* end.
*/
deleteConflicts.removeIf(next -> deletedResources.contains(next.getTargetId().toVersionless()));
validateDeleteConflictsEmptyOrThrowException(deleteConflicts);
/*
* Perform ID substitutions and then index each resource we have saved
*/
FhirTerser terser = getContext().newTerser();
for (DaoMethodOutcome nextOutcome : idToPersistedOutcome.values()) {
IResource nextResource = (IResource) nextOutcome.getResource();
if (nextResource == null) {
continue;
}
// References
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
for (BaseResourceReferenceDt nextRef : allRefs) {
IdDt nextId = nextRef.getReference();
if (!nextId.hasIdPart()) {
continue;
}
if (idSubstitutions.containsKey(nextId)) {
IdDt newId = idSubstitutions.get(nextId);
ourLog.debug(" * Replacing resource ref {} with {}", nextId, newId);
nextRef.setReference(newId);
} else {
ourLog.debug(" * Reference [{}] does not exist in bundle", nextId);
}
}
// URIs
List<UriDt> allUris = terser.getAllPopulatedChildElementsOfType(nextResource, UriDt.class);
for (UriDt nextRef : allUris) {
if (nextRef instanceof IIdType) {
continue; // No substitution on the resource ID itself!
}
IdDt nextUriString = new IdDt(nextRef.getValueAsString());
if (idSubstitutions.containsKey(nextUriString)) {
IdDt newId = idSubstitutions.get(nextUriString);
ourLog.debug(" * Replacing resource ref {} with {}", nextUriString, newId);
nextRef.setValue(newId.getValue());
} else {
ourLog.debug(" * Reference [{}] does not exist in bundle", nextUriString);
}
}
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
if (updatedEntities.contains(nextOutcome.getEntity())) {
updateInternal(theRequestDetails, nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
updateEntity(theRequestDetails, nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, updateTime, false, true);
}
}
myEntityManager.flush();
/*
* Double check we didn't allow any duplicates we shouldn't have
*/
for (Entry nextEntry : theRequest.getEntry()) {
if (nextEntry.getRequest().getMethodElement().getValueAsEnum() == HTTPVerbEnum.POST) {
String matchUrl = nextEntry.getRequest().getIfNoneExist();
if (isNotBlank(matchUrl)) {
IFhirResourceDao<?> resourceDao = getDao(nextEntry.getResource().getClass());
Set<Long> val = resourceDao.processMatchUrl(matchUrl);
if (val.size() > 1) {
throw new InvalidRequestException(
"Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
}
}
}
}
for (IdDt next : allIds) {
IdDt replacement = idSubstitutions.get(next);
if (replacement == null) {
continue;
}
if (replacement.equals(next)) {
continue;
}
ourLog.debug("Placeholder resource ID \"{}\" was replaced with permanent ID \"{}\"", next, replacement);
}
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.execute(t->{
handleTransactionWriteOperations(theRequestDetails, theRequest, theActionName, updateTime, allIds, idSubstitutions, idToPersistedOutcome, response, originalRequestOrder, deletedResources, deleteConflicts, entriesToProcess, nonUpdatedEntities, updatedEntities);
return null;
});
/*
* Loop through the request and process any entries of type GET
@ -447,7 +245,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
for (NameValuePair next : parameters) {
paramValues.put(next.getName(), next.getValue());
}
for (java.util.Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
for (Map.Entry<String, Collection<String>> nextParamEntry : paramValues.asMap().entrySet()) {
String[] nextValue = nextParamEntry.getValue().toArray(new String[nextParamEntry.getValue().size()]);
requestDetails.addParameter(nextParamEntry.getKey(), nextValue);
}
@ -490,10 +288,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
}
ourLog.info("Flushing context after {}", theActionName);
myEntityManager.flush();
for (java.util.Map.Entry<Entry, ResourceTable> nextEntry : entriesToProcess.entrySet()) {
for (Map.Entry<Entry, ResourceTable> nextEntry : entriesToProcess.entrySet()) {
nextEntry.getKey().getResponse().setLocation(nextEntry.getValue().getIdDt().toUnqualified().getValue());
nextEntry.getKey().getResponse().setEtag(nextEntry.getValue().getIdDt().getVersionIdPart());
}
@ -507,6 +302,229 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
return response;
}
private void handleTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date theUpdateTime, Set<IdDt> theAllIds, Map<IdDt, IdDt> theIdSubstitutions, Map<IdDt, DaoMethodOutcome> theIdToPersistedOutcome, Bundle theResponse, IdentityHashMap<Entry, Integer> theOriginalRequestOrder, List<IIdType> theDeletedResources, List<DeleteConflict> theDeleteConflicts, Map<Entry, ResourceTable> theEntriesToProcess, Set<ResourceTable> theNonUpdatedEntities, Set<ResourceTable> theUpdatedEntities) {
/*
* Loop through the request and process any entries of type
* PUT, POST or DELETE
*/
for (int i = 0; i < theRequest.getEntry().size(); i++) {
if (i % 100 == 0) {
ourLog.debug("Processed {} non-GET entries out of {}", i, theRequest.getEntry().size());
}
Entry nextReqEntry = theRequest.getEntry().get(i);
IResource res = nextReqEntry.getResource();
IdDt nextResourceId = null;
if (res != null) {
nextResourceId = res.getId();
if (!nextResourceId.hasIdPart()) {
if (isNotBlank(nextReqEntry.getFullUrl())) {
nextResourceId = new IdDt(nextReqEntry.getFullUrl());
}
}
if (nextResourceId.hasIdPart() && nextResourceId.getIdPart().matches("[a-zA-Z]+\\:.*") && !isPlaceholder(nextResourceId)) {
throw new InvalidRequestException("Invalid placeholder ID found: " + nextResourceId.getIdPart() + " - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'");
}
if (nextResourceId.hasIdPart() && !nextResourceId.hasResourceType() && !isPlaceholder(nextResourceId)) {
nextResourceId = new IdDt(toResourceName(res.getClass()), nextResourceId.getIdPart());
res.setId(nextResourceId);
}
/*
* Ensure that the bundle doesn't have any duplicates, since this causes all kinds of weirdness
*/
if (isPlaceholder(nextResourceId)) {
if (!theAllIds.add(nextResourceId)) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextResourceId));
}
} else if (nextResourceId.hasResourceType() && nextResourceId.hasIdPart()) {
IdDt nextId = nextResourceId.toUnqualifiedVersionless();
if (!theAllIds.add(nextId)) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionContainsMultipleWithDuplicateId", nextId));
}
}
}
HTTPVerbEnum verb = nextReqEntry.getRequest().getMethodElement().getValueAsEnum();
if (verb == null) {
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionEntryHasInvalidVerb", nextReqEntry.getRequest().getMethod()));
}
String resourceType = res != null ? getContext().getResourceDefinition(res).getName() : null;
Entry nextRespEntry = theResponse.getEntry().get(theOriginalRequestOrder.get(nextReqEntry));
switch (verb) {
case POST: {
// CREATE
@SuppressWarnings("rawtypes")
IFhirResourceDao resourceDao = getDaoOrThrowException(res.getClass());
res.setId((String) null);
DaoMethodOutcome outcome;
outcome = resourceDao.create(res, nextReqEntry.getRequest().getIfNoneExist(), false, theRequestDetails);
handleTransactionCreateOrUpdateOutcome(theIdSubstitutions, theIdToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
theEntriesToProcess.put(nextRespEntry, outcome.getEntity());
if (outcome.getCreated() == false) {
theNonUpdatedEntities.add(outcome.getEntity());
}
break;
}
case DELETE: {
// DELETE
String url = extractTransactionUrlOrThrowException(nextReqEntry, verb);
UrlParts parts = UrlUtil.parseUrl(url);
IFhirResourceDao<? extends IBaseResource> dao = toDao(parts, verb.getCode(), url);
int status = Constants.STATUS_HTTP_204_NO_CONTENT;
if (parts.getResourceId() != null) {
DaoMethodOutcome outcome = dao.delete(new IdDt(parts.getResourceType(), parts.getResourceId()), theDeleteConflicts, theRequestDetails);
if (outcome.getEntity() != null) {
theDeletedResources.add(outcome.getId().toUnqualifiedVersionless());
theEntriesToProcess.put(nextRespEntry, outcome.getEntity());
}
} else {
DeleteMethodOutcome deleteOutcome = dao.deleteByUrl(parts.getResourceType() + '?' + parts.getParams(), theDeleteConflicts, theRequestDetails);
List<ResourceTable> allDeleted = deleteOutcome.getDeletedEntities();
for (ResourceTable deleted : allDeleted) {
theDeletedResources.add(deleted.getIdDt().toUnqualifiedVersionless());
}
if (allDeleted.isEmpty()) {
status = Constants.STATUS_HTTP_404_NOT_FOUND;
}
}
nextRespEntry.getResponse().setStatus(toStatusString(status));
break;
}
case PUT: {
// UPDATE
@SuppressWarnings("rawtypes")
IFhirResourceDao resourceDao = getDaoOrThrowException(res.getClass());
DaoMethodOutcome outcome;
String url = extractTransactionUrlOrThrowException(nextReqEntry, verb);
UrlParts parts = UrlUtil.parseUrl(url);
if (isNotBlank(parts.getResourceId())) {
res.setId(new IdDt(parts.getResourceType(), parts.getResourceId()));
outcome = resourceDao.update(res, null, false, theRequestDetails);
} else {
res.setId((String) null);
outcome = resourceDao.update(res, parts.getResourceType() + '?' + parts.getParams(), false, theRequestDetails);
}
if (outcome.getCreated() == Boolean.FALSE) {
theUpdatedEntities.add(outcome.getEntity());
}
handleTransactionCreateOrUpdateOutcome(theIdSubstitutions, theIdToPersistedOutcome, nextResourceId, outcome, nextRespEntry, resourceType, res);
theEntriesToProcess.put(nextRespEntry, outcome.getEntity());
break;
}
case GET:
break;
}
}
/*
* Make sure that there are no conflicts from deletions. E.g. we can't delete something
* if something else has a reference to it.. Unless the thing that has a reference to it
* was also deleted as a part of this transaction, which is why we check this now at the
* end.
*/
theDeleteConflicts.removeIf(next -> theDeletedResources.contains(next.getTargetId().toVersionless()));
validateDeleteConflictsEmptyOrThrowException(theDeleteConflicts);
/*
* Perform ID substitutions and then index each resource we have saved
*/
FhirTerser terser = getContext().newTerser();
for (DaoMethodOutcome nextOutcome : theIdToPersistedOutcome.values()) {
IResource nextResource = (IResource) nextOutcome.getResource();
if (nextResource == null) {
continue;
}
// References
List<BaseResourceReferenceDt> allRefs = terser.getAllPopulatedChildElementsOfType(nextResource, BaseResourceReferenceDt.class);
for (BaseResourceReferenceDt nextRef : allRefs) {
IdDt nextId = nextRef.getReference();
if (!nextId.hasIdPart()) {
continue;
}
if (theIdSubstitutions.containsKey(nextId)) {
IdDt newId = theIdSubstitutions.get(nextId);
ourLog.debug(" * Replacing resource ref {} with {}", nextId, newId);
nextRef.setReference(newId);
} else {
ourLog.debug(" * Reference [{}] does not exist in bundle", nextId);
}
}
// URIs
List<UriDt> allUris = terser.getAllPopulatedChildElementsOfType(nextResource, UriDt.class);
for (UriDt nextRef : allUris) {
if (nextRef instanceof IIdType) {
continue; // No substitution on the resource ID itself!
}
IdDt nextUriString = new IdDt(nextRef.getValueAsString());
if (theIdSubstitutions.containsKey(nextUriString)) {
IdDt newId = theIdSubstitutions.get(nextUriString);
ourLog.debug(" * Replacing resource ref {} with {}", nextUriString, newId);
nextRef.setValue(newId.getValue());
} else {
ourLog.debug(" * Reference [{}] does not exist in bundle", nextUriString);
}
}
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
if (theUpdatedEntities.contains(nextOutcome.getEntity())) {
updateInternal(theRequestDetails, nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
} else if (!theNonUpdatedEntities.contains(nextOutcome.getEntity())) {
updateEntity(theRequestDetails, nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, theUpdateTime, false, true);
}
}
myEntityManager.flush();
/*
* Double check we didn't allow any duplicates we shouldn't have
*/
for (Entry nextEntry : theRequest.getEntry()) {
if (nextEntry.getRequest().getMethodElement().getValueAsEnum() == HTTPVerbEnum.POST) {
String matchUrl = nextEntry.getRequest().getIfNoneExist();
if (isNotBlank(matchUrl)) {
IFhirResourceDao<?> resourceDao = getDao(nextEntry.getResource().getClass());
Set<Long> val = resourceDao.processMatchUrl(matchUrl);
if (val.size() > 1) {
throw new InvalidRequestException(
"Unable to process " + theActionName + " - Request would cause multiple resources to match URL: \"" + matchUrl + "\". Does transaction request contain duplicates?");
}
}
}
}
for (IdDt next : theAllIds) {
IdDt replacement = theIdSubstitutions.get(next);
if (replacement == null) {
continue;
}
if (replacement.equals(next)) {
continue;
}
ourLog.debug("Placeholder resource ID \"{}\" was replaced with permanent ID \"{}\"", next, replacement);
}
}
private String extractTransactionUrlOrThrowException(Entry nextEntry, HTTPVerbEnum verb) {
String url = nextEntry.getRequest().getUrl();
if (isBlank(url)) {
@ -595,7 +613,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
return retVal;
}
@Transactional(propagation = Propagation.REQUIRED)
@Transactional(propagation = Propagation.NEVER)
@Override
public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) {
if (theRequestDetails != null) {

View File

@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao;
* #L%
*/
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.entity.ResourceTable;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.Constants;
@ -41,6 +42,7 @@ import org.hibernate.search.query.dsl.BooleanJunction;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hl7.fhir.dstu3.model.BaseResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
@ -50,12 +52,15 @@ import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FulltextSearchSvcImpl extends BaseHapiFhirDao<IBaseResource> implements IFulltextSearchSvc {
public class FulltextSearchSvcImpl implements IFulltextSearchSvc {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FulltextSearchSvcImpl.class);
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager myEntityManager;
@Autowired
protected IForcedIdDao myForcedIdDao;
/**
* Constructor
*/

View File

@ -112,8 +112,6 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
TagList getAllResourceTags(RequestDetails theRequestDetails);
<R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType);
Class<T> getResourceType();
TagList getTags(IIdType theResourceId, RequestDetails theRequestDetails);

View File

@ -25,8 +25,6 @@ import ca.uhn.fhir.jpa.util.ExpungeOutcome;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nullable;
import java.util.Date;
@ -40,12 +38,13 @@ public interface IFhirSystemDao<T, MT> extends IDao {
ExpungeOutcome expunge(ExpungeOptions theExpungeOptions);
@SuppressWarnings("unchecked")
<R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType);
Map<String, Long> getResourceCounts();
/**
*Returns a cached count of resources using a cache that regularly
* Returns a cached count of resources using a cache that regularly
* refreshes in the background. This method will never
*/
@Nullable

View File

@ -14,6 +14,8 @@ import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.dstu3.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@ -63,6 +65,7 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
*/
@Override
@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
@Transactional(propagation = Propagation.NEVER)
public void performReindexingPass() {
if (getConfig().isSchedulingDisabled()) {
return;

View File

@ -11,9 +11,12 @@ import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.annotation.PostConstruct;
import javax.transaction.Transactional;
import javax.transaction.Transactional.TxType;
import java.util.Collections;
@ -42,34 +45,25 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
*/
@Transactional(value = TxType.REQUIRED)
public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3 {
public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3, ApplicationContextAware {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JpaValidationSupportDstu3.class);
@Autowired
@Qualifier("myStructureDefinitionDaoDstu3")
private IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
@Autowired
@Qualifier("myValueSetDaoDstu3")
private IFhirResourceDao<ValueSet> myValueSetDao;
@Autowired
@Qualifier("myQuestionnaireDaoDstu3")
private IFhirResourceDao<Questionnaire> myQuestionnaireDao;
@Autowired
@Qualifier("myCodeSystemDaoDstu3")
private IFhirResourceDao<CodeSystem> myCodeSystemDao;
@Autowired
private FhirContext myDstu3Ctx;
private ApplicationContext myApplicationContext;
/**
* Constructor
*/
public JpaValidationSupportDstu3() {
super();
}
@Override
@Transactional(value = TxType.SUPPORTS)
public ValueSetExpansionComponent expandValueSet(FhirContext theCtx, ConceptSetComponent theInclude) {
@ -168,6 +162,19 @@ public class JpaValidationSupportDstu3 implements IJpaValidationSupportDstu3 {
return false;
}
@Override
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
myApplicationContext = theApplicationContext;
}
@PostConstruct
public void start() {
myStructureDefinitionDao = myApplicationContext.getBean("myStructureDefinitionDaoDstu3", IFhirResourceDao.class);
myValueSetDao = myApplicationContext.getBean("myValueSetDaoDstu3", IFhirResourceDao.class);
myQuestionnaireDao = myApplicationContext.getBean("myQuestionnaireDaoDstu3", IFhirResourceDao.class);
myCodeSystemDao = myApplicationContext.getBean("myCodeSystemDaoDstu3", IFhirResourceDao.class);
}
@Override
@Transactional(value = TxType.SUPPORTS)
public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) {

View File

@ -13,6 +13,8 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@ -57,6 +59,7 @@ public class FhirResourceDaoSearchParameterR4 extends FhirResourceDaoR4<SearchPa
*/
@Override
@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
@Transactional(propagation = Propagation.NEVER)
public void performReindexingPass() {
if (getConfig().isSchedulingDisabled()) {
return;

View File

@ -11,9 +11,12 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.annotation.PostConstruct;
import javax.transaction.Transactional;
import javax.transaction.Transactional.TxType;
import java.util.Collections;
@ -40,29 +43,22 @@ import java.util.List;
*/
@Transactional(value = TxType.REQUIRED)
public class JpaValidationSupportR4 implements IJpaValidationSupportR4 {
public class JpaValidationSupportR4 implements IJpaValidationSupportR4, ApplicationContextAware {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JpaValidationSupportR4.class);
@Autowired
@Qualifier("myStructureDefinitionDaoR4")
private IFhirResourceDao<StructureDefinition> myStructureDefinitionDao;
@Autowired
@Qualifier("myValueSetDaoR4")
private IFhirResourceDao<ValueSet> myValueSetDao;
@Autowired
@Qualifier("myQuestionnaireDaoR4")
private IFhirResourceDao<Questionnaire> myQuestionnaireDao;
@Autowired
@Qualifier("myCodeSystemDaoR4")
private IFhirResourceDao<CodeSystem> myCodeSystemDao;
@Autowired
private FhirContext myR4Ctx;
private ApplicationContext myApplicationContext;
/**
* Constructor
*/
public JpaValidationSupportR4() {
super();
}
@ -163,6 +159,19 @@ public class JpaValidationSupportR4 implements IJpaValidationSupportR4 {
return false;
}
@Override
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
myApplicationContext = theApplicationContext;
}
@PostConstruct
public void start() {
myStructureDefinitionDao = myApplicationContext.getBean("myStructureDefinitionDaoR4", IFhirResourceDao.class);
myValueSetDao = myApplicationContext.getBean("myValueSetDaoR4", IFhirResourceDao.class);
myQuestionnaireDao = myApplicationContext.getBean("myQuestionnaireDaoR4", IFhirResourceDao.class);
myCodeSystemDao = myApplicationContext.getBean("myCodeSystemDaoR4", IFhirResourceDao.class);
}
@Override
@Transactional(value = TxType.SUPPORTS)
public CodeValidationResult validateCode(FhirContext theCtx, String theCodeSystem, String theCode, String theDisplay) {

View File

@ -77,7 +77,7 @@ public class StaleSearchDeletingSvcImpl implements IStaleSearchDeletingSvc {
}
@Override
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Transactional(propagation = Propagation.NEVER)
public void pollForStaleSearchesAndDeleteThem() {
if (!myDaoConfig.isExpireSearchResults()) {
return;
@ -127,7 +127,7 @@ public class StaleSearchDeletingSvcImpl implements IStaleSearchDeletingSvc {
}
@Scheduled(fixedDelay = DEFAULT_CUTOFF_SLACK)
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Transactional(propagation = Propagation.NEVER)
@Override
public synchronized void schedulePollForStaleSearches() {
if (!myDaoConfig.isSchedulingDisabled()) {

View File

@ -67,7 +67,7 @@ public abstract class BaseSubscriptionDeliverySubscriber extends BaseSubscriptio
// can have placeholder IDs in them.
IIdType payloadId = msg.getPayloadId(getContext());
Class type = getContext().getResourceDefinition(payloadId.getResourceType()).getImplementingClass();
IFhirResourceDao dao = getSubscriptionDao().getDao(type);
IFhirResourceDao dao = getSubscriptionInterceptor().getDao(type);
IBaseResource loadedPayload;
try {
loadedPayload = dao.read(payloadId);

View File

@ -28,7 +28,6 @@ import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
@ -37,6 +36,7 @@ import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
import ca.uhn.fhir.util.StopWatch;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
@ -99,6 +99,7 @@ public abstract class BaseSubscriptionInterceptor<S extends IBaseResource> exten
@Autowired
@Qualifier(BaseConfig.TASK_EXECUTOR_NAME)
private AsyncTaskExecutor myAsyncTaskExecutor;
private Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> myResourceTypeToDao;
/**
* Constructor
@ -243,6 +244,26 @@ public abstract class BaseSubscriptionInterceptor<S extends IBaseResource> exten
public abstract Subscription.SubscriptionChannelType getChannelType();
@SuppressWarnings("unchecked")
public <R extends IBaseResource> IFhirResourceDao<R> getDao(Class<R> theType) {
if (myResourceTypeToDao == null) {
Map<Class<? extends IBaseResource>, IFhirResourceDao<?>> theResourceTypeToDao = new HashMap<>();
for (IFhirResourceDao<?> next : myResourceDaos) {
theResourceTypeToDao.put(next.getResourceType(), next);
}
if (this instanceof IFhirResourceDao<?>) {
IFhirResourceDao<?> thiz = (IFhirResourceDao<?>) this;
theResourceTypeToDao.put(thiz.getResourceType(), thiz);
}
myResourceTypeToDao = theResourceTypeToDao;
}
IFhirResourceDao<R> dao = (IFhirResourceDao<R>) myResourceTypeToDao.get(theType);
return dao;
}
public SubscribableChannel getDeliveryChannel() {
return myDeliveryChannel;
}

View File

@ -140,7 +140,7 @@ public class SubscriptionCheckingSubscriber extends BaseSubscriptionSubscriber {
RequestDetails req = new ServletSubRequestDetails();
req.setSubRequest(true);
IFhirResourceDao<? extends IBaseResource> responseDao = getSubscriptionDao().getDao(responseResourceDef.getImplementingClass());
IFhirResourceDao<? extends IBaseResource> responseDao = getSubscriptionInterceptor().getDao(responseResourceDef.getImplementingClass());
responseCriteriaUrl.setLoadSynchronousUpTo(1);
IBundleProvider responseResults = responseDao.search(responseCriteriaUrl, req);

View File

@ -123,7 +123,7 @@ public class SubscriptionDeliveringRestHookSubscriber extends BaseSubscriptionDe
IBaseResource payloadResource = theMsg.getPayload(getContext());
if (theSubscription.getRestHookDetails().isDeliverLatestVersion()) {
IFhirResourceDao dao = getSubscriptionDao().getDao(payloadResource.getClass());
IFhirResourceDao dao = getSubscriptionInterceptor().getDao(payloadResource.getClass());
try {
payloadResource = dao.read(payloadResource.getIdElement().toVersionless());
} catch (ResourceGoneException e) {

View File

@ -31,7 +31,6 @@ import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
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.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ObjectUtil;
import ca.uhn.fhir.util.StopWatch;
@ -56,7 +55,10 @@ import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.ValueSet;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Scheduled;
@ -80,7 +82,7 @@ import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc {
public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc, ApplicationContextAware {
public static final int DEFAULT_FETCH_SIZE = 250;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiTerminologySvcImpl.class);
@ -123,14 +125,11 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc
private boolean myProcessDeferred = true;
@Autowired
private PlatformTransactionManager myTransactionMgr;
@Autowired(required = false)
private IFhirResourceDaoCodeSystem<?, ?, ?> myCodeSystemResourceDao;
private Cache<TranslationQuery, List<TermConceptMapGroupElementTarget>> myTranslationCache;
private Cache<TranslationQuery, List<TermConceptMapGroupElement>> myTranslationWithReverseCache;
private int myFetchSize = DEFAULT_FETCH_SIZE;
private ApplicationContext myApplicationContext;
private void addCodeIfNotAlreadyAdded(String theCodeSystem, ValueSet.ValueSetExpansionComponent theExpansionComponent, Set<String> theAddedCodes, TermConcept theConcept) {
if (theAddedCodes.add(theConcept.getCode())) {
@ -207,6 +206,32 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc
.build();
}
/**
* This method is present only for unit tests, do not call from client code
*/
@VisibleForTesting
public void clearDeferred() {
myDeferredValueSets.clear();
myDeferredConceptMaps.clear();
myDeferredConcepts.clear();
}
/**
* This method is present only for unit tests, do not call from client code
*/
@VisibleForTesting
public void clearTranslationCache() {
myTranslationCache.invalidateAll();
}
/**
* This method is present only for unit tests, do not call from client code
*/
@VisibleForTesting()
public void clearTranslationWithReverseCache() {
myTranslationWithReverseCache.invalidateAll();
}
protected abstract IIdType createOrUpdateCodeSystem(CodeSystem theCodeSystemResource);
protected abstract void createOrUpdateConceptMap(ConceptMap theNextConceptMap);
@ -788,11 +813,21 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc
}
@Override
public void setApplicationContext(ApplicationContext theApplicationContext) throws BeansException {
myApplicationContext = theApplicationContext;
}
@Override
public void setProcessDeferred(boolean theProcessDeferred) {
myProcessDeferred = theProcessDeferred;
}
@PostConstruct
public void start() {
myCodeSystemResourceDao = myApplicationContext.getBean(IFhirResourceDaoCodeSystem.class);
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void storeNewCodeSystemVersion(Long theCodeSystemResourcePid, String theSystemUri, String theSystemName, TermCodeSystemVersion theCodeSystemVersion) {
@ -1258,32 +1293,6 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc
ourLastResultsFromTranslationWithReverseCache = false;
}
/**
* This method is present only for unit tests, do not call from client code
*/
@VisibleForTesting
public void clearTranslationCache() {
myTranslationCache.invalidateAll();
}
/**
* This method is present only for unit tests, do not call from client code
*/
@VisibleForTesting
public void clearDeferred() {
myDeferredValueSets.clear();
myDeferredConceptMaps.clear();
myDeferredConcepts.clear();
}
/**
* This method is present only for unit tests, do not call from client code
*/
@VisibleForTesting()
public void clearTranslationWithReverseCache() {
myTranslationWithReverseCache.invalidateAll();
}
/**
* This method is present only for unit tests, do not call from client code
*/

View File

@ -113,6 +113,7 @@ public class LoincHandler implements IRecordHandler {
ourLog.warn("Unable to find part code with TYPE[{}] and NAME[{}]", key.getPartType(), key.getPartName());
}
break;
case DECIMAL:
case CODE:
case INTEGER:
case BOOLEAN:

View File

@ -252,6 +252,7 @@ public class ConnectionWrapper implements Connection {
@Override
public void setReadOnly(boolean theReadOnly) throws SQLException {
ourLog.info("Setting connection as readonly");
myWrap.setReadOnly(theReadOnly);
}

View File

@ -4,8 +4,11 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.validation.ResultSeverityEnum;
import net.ttddyy.dsproxy.listener.ThreadQueryCountHolder;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
import org.apache.commons.dbcp2.BasicDataSource;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@ -15,11 +18,35 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
@Configuration
@EnableTransactionManagement()
public class TestDstu2Config extends BaseJavaConfigDstu2 {
private static final Logger ourLog = LoggerFactory.getLogger(TestDstu2Config.class);
private static int ourMaxThreads;
static {
/*
* We use a randomized number of maximum threads in order to try
* and catch any potential deadlocks caused by database connection
* starvation
*/
ourMaxThreads = (int) (Math.random() * 6.0) + 1;
}
private Exception myLastStackTrace;
private String myLastStackTraceThreadName;
@Bean(name="maxDatabaseThreadsForTest")
public Integer getMaxThread(){
return ourMaxThreads;
}
@Bean()
public DaoConfig daoConfig() {
@ -28,21 +55,73 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
@Bean()
public DataSource dataSource() {
BasicDataSource retVal = new BasicDataSource();
BasicDataSource retVal = new BasicDataSource() {
@Override
public Connection getConnection() throws SQLException {
ConnectionWrapper retVal;
try {
retVal = new ConnectionWrapper(super.getConnection());
} catch (Exception e) {
ourLog.error("Exceeded maximum wait for connection", e);
logGetConnectionStackTrace();
// if ("true".equals(System.getStringProperty("ci"))) {
fail("Exceeded maximum wait for connection: " + e.toString());
// }
// System.exit(1);
retVal = null;
}
try {
throw new Exception();
} catch (Exception e) {
myLastStackTrace = e;
myLastStackTraceThreadName = Thread.currentThread().getName();
}
return retVal;
}
private void logGetConnectionStackTrace() {
StringBuilder b = new StringBuilder();
b.append("Last connection request stack trace:");
for (StackTraceElement next : myLastStackTrace.getStackTrace()) {
b.append("\n ");
b.append(next.getClassName());
b.append(".");
b.append(next.getMethodName());
b.append("(");
b.append(next.getFileName());
b.append(":");
b.append(next.getLineNumber());
b.append(")");
}
ourLog.info(b.toString());
ourLog.info("Last connection thread: {}", myLastStackTraceThreadName);
}
};
retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
retVal.setUrl("jdbc:derby:memory:myUnitTestDBDstu2;create=true");
retVal.setMaxWaitMillis(10000);
retVal.setUsername("");
retVal.setPassword("");
return retVal;
}
@Bean()
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager retVal = new JpaTransactionManager();
retVal.setEntityManagerFactory(entityManagerFactory);
return retVal;
retVal.setMaxTotal(ourMaxThreads);
DataSource dataSource = ProxyDataSourceBuilder
.create(retVal)
// .logQueryBySlf4j(SLF4JLogLevel.INFO, "SQL")
.logSlowQueryBySlf4j(10, TimeUnit.SECONDS)
.countQuery(new ThreadQueryCountHolder())
.build();
return dataSource;
}
@Override
@Bean()
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory();
@ -60,7 +139,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
extraProperties.put("hibernate.dialect", "ca.uhn.fhir.jpa.util.DerbyTenSevenHapiFhirDialect");
extraProperties.put("hibernate.search.model_mapping", LuceneSearchMappingFactory.class.getName());
extraProperties.put("hibernate.search.default.directory_provider", "ram");
extraProperties.put("hibernate.search.lucene_version","LUCENE_CURRENT");
extraProperties.put("hibernate.search.lucene_version", "LUCENE_CURRENT");
return extraProperties;
}
@ -79,4 +158,11 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
return requestValidator;
}
@Bean()
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager retVal = new JpaTransactionManager();
retVal.setEntityManagerFactory(entityManagerFactory);
return retVal;
}
}

View File

@ -20,6 +20,10 @@ import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
@ -30,6 +34,8 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Rule;
import org.mockito.Mockito;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
@ -38,8 +44,11 @@ import org.springframework.transaction.support.TransactionTemplate;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import static ca.uhn.fhir.util.TestUtil.randomizeLocale;
import static org.junit.Assert.*;
@ -64,7 +73,7 @@ public abstract class BaseJpaTest {
protected IRequestOperationCallback myRequestOperationCallback = mock(IRequestOperationCallback.class);
@After
public final void afterPerformCleanup() {
public void afterPerformCleanup() {
BaseHapiFhirResourceDao.setDisableIncrementOnUpdateForUnitTest(false);
}
@ -78,6 +87,32 @@ public abstract class BaseJpaTest {
when(mySrd.getHeaders(eq(JpaConstants.HEADER_META_SNAPSHOT_MODE))).thenReturn(new ArrayList<>());
}
@After
public void afterValidateNoTransaction() {
PlatformTransactionManager txManager = getTxManager();
if (txManager != null) {
JpaTransactionManager hibernateTxManager = (JpaTransactionManager) txManager;
SessionFactory sessionFactory = (SessionFactory) hibernateTxManager.getEntityManagerFactory();
AtomicBoolean isReadOnly = new AtomicBoolean();
Session currentSession;
try {
currentSession = sessionFactory.getCurrentSession();
} catch (HibernateException e) {
currentSession = null;
}
if (currentSession != null) {
currentSession.doWork(new Work() {
public void execute(Connection connection) throws SQLException {
isReadOnly.set(connection.isReadOnly());
}
});
assertFalse(isReadOnly.get());
}
}
}
@Before
public void beforeRandomizeLocale() {
randomizeLocale();

View File

@ -1,10 +1,9 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.TestUtil;
import com.phloc.commons.compare.ReverseComparator;
import org.apache.commons.collections4.comparators.ReverseComparator;
import org.apache.commons.dbcp2.BasicDataSource;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Bundle.BundleType;

View File

@ -44,11 +44,7 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.util.AopTestUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.EntityManager;
import java.io.IOException;

View File

@ -49,6 +49,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
protected static SubscriptionRestHookInterceptor ourRestHookSubscriptionInterceptor;
protected static DatabaseBackedPagingProvider ourPagingProvider;
protected static PlatformTransactionManager ourTxManager;
protected static Integer ourConnectionPoolSize;
public BaseResourceProviderDstu2Test() {
super();
@ -84,6 +85,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
ourRestServer.setServerConformanceProvider(confProvider);
ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class);
ourConnectionPoolSize = myAppCtx.getBean("maxDatabaseThreadsForTest", Integer.class);
ourRestServer.setPagingProvider(ourPagingProvider);
Server server = new Server(ourPort);

View File

@ -1,41 +1,58 @@
package ca.uhn.fhir.jpa.provider;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.*;
import org.apache.http.entity.*;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.*;
import org.junit.Test;
import org.springframework.test.util.AopTestUtils;
import com.google.common.base.Charsets;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.dstu2.composite.*;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.*;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.valueset.*;
import ca.uhn.fhir.model.primitive.*;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.util.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.*;
import org.springframework.test.util.AopTestUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
@ -50,7 +67,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(null);
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(SearchCoordinatorSvcImpl.DEFAULT_SYNC_SIZE);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(false);
@ -107,7 +124,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
}
@Test
public void testBundleCreateWithTypeTransaction() throws Exception {
IGenericClient client = ourClient;
@ -182,22 +199,22 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
ourClient.transaction().withResources(resources).prettyPrint().encodedXml().execute();
Bundle found = ourClient
.search()
.forResource(Organization.class)
.where(Organization.NAME.matches().value("rpdstu2_testCountParam_01"))
.count(10)
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Organization.class)
.where(Organization.NAME.matches().value("rpdstu2_testCountParam_01"))
.count(10)
.returnBundle(Bundle.class)
.execute();
assertEquals(100, found.getTotalElement().getValue().intValue());
assertEquals(10, found.getEntry().size());
found = ourClient
.search()
.forResource(Organization.class)
.where(Organization.NAME.matches().value("rpdstu2_testCountParam_01"))
.count(999)
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Organization.class)
.where(Organization.NAME.matches().value("rpdstu2_testCountParam_01"))
.count(999)
.returnBundle(Bundle.class)
.execute();
assertEquals(100, found.getTotalElement().getValue().intValue());
assertEquals(50, found.getEntry().size());
@ -208,15 +225,15 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
*/
@Test
public void testCreateAndUpdateBinary() throws ClientProtocolException, Exception {
byte[] arr = { 1, 21, 74, 123, -44 };
byte[] arr = {1, 21, 74, 123, -44};
Binary binary = new Binary();
binary.setContent(arr);
binary.setContentType("dansk");
binary.addUndeclaredExtension(true, "bobobo", new StringDt("hey there"));
IIdType resource = ourClient.create().resource(binary).execute().getId();
Binary fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
assertEquals("1", fromDB.getId().getVersionIdPart());
@ -231,7 +248,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
} finally {
IOUtils.closeQuietly(resp);
}
fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
assertEquals("2", fromDB.getId().getVersionIdPart());
@ -247,12 +264,12 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
} finally {
IOUtils.closeQuietly(resp);
}
fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
assertEquals("3", fromDB.getId().getVersionIdPart());
// Now an update with the wrong ID in the body
arr[0] = 4;
binary.setContent(arr);
binary.setId("");
@ -265,7 +282,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
} finally {
IOUtils.closeQuietly(resp);
}
fromDB = ourClient.read().resource(Binary.class).withId(resource.toVersionless()).execute();
assertEquals("3", fromDB.getId().getVersionIdPart());
@ -441,7 +458,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(400, response.getStatusLine().getStatusCode());
OperationOutcome oo = myFhirCtx.newXmlParser().parseResource(OperationOutcome.class, responseString);
assertEquals("Can not create resource with ID \"2\", ID must not be supplied on a create (POST) operation (use an HTTP PUT / update operation if you wish to supply an ID)",
oo.getIssue().get(0).getDiagnostics());
oo.getIssue().get(0).getDiagnostics());
} finally {
response.getEntity().getContent().close();
response.close();
@ -494,7 +511,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(e1id.toUnqualifiedVersionless(), BundleUtil.toListOfResourcesOfType(myFhirCtx, res, Encounter.class).get(0).getIdElement().toUnqualifiedVersionless());
}
@Test
public void testDeleteConditionalMultiple() {
String methodName = "testDeleteConditionalMultiple";
@ -522,7 +539,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
fail();
} catch (PreconditionFailedException e) {
assertEquals("HTTP 412 Precondition Failed: Failed to DELETE resource with match URL \"Patient?identifier=testDeleteConditionalMultiple\" because this search matched 2 resources",
e.getMessage());
e.getMessage());
}
// Not deleted yet..
@ -682,12 +699,12 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IGenericClient client = ourClient;
int initialSize = client
.search()
.forResource(DiagnosticOrder.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(DiagnosticOrder.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
DiagnosticOrder res = new DiagnosticOrder();
res.addIdentifier().setSystem("urn:foo").setValue("123");
@ -695,12 +712,12 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
client.create().resource(res).execute();
int newSize = client
.search()
.forResource(DiagnosticOrder.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(DiagnosticOrder.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize);
@ -717,23 +734,23 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IGenericClient client = ourClient;
int initialSize = client
.search()
.forResource(DocumentManifest.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(DocumentManifest.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentmanifest.json"), StandardCharsets.UTF_8);
client.create().resource(resBody).execute();
int newSize = client
.search()
.forResource(DocumentManifest.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(DocumentManifest.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize);
@ -747,23 +764,23 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IGenericClient client = ourClient;
int initialSize = client
.search()
.forResource(DocumentReference.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(DocumentReference.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/documentreference.json"), Charsets.UTF_8);
client.create().resource(resBody).execute();
int newSize = client
.search()
.forResource(DocumentReference.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(DocumentReference.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize);
@ -934,7 +951,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
List<IIdType> actual;
StringAndListParam param;
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] { ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart() });
ourLog.info("Pt1:{} Pt2:{} Obs1:{} Obs2:{} Obs3:{}", new Object[] {ptId1.getIdPart(), ptId2.getIdPart(), obsId1.getIdPart(), obsId2.getIdPart(), obsId3.getIdPart()});
param = new StringAndListParam();
param.addAnd(new StringOrListParam().addOr(new StringParam("obsvalue1")));
@ -1203,7 +1220,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
get = new HttpGet(ourServerBase + "/Patient/" + pId.getIdPart() + "/$everything?_lastUpdated=%3E" + new InstantDt(new Date(time2)).getValueAsString() + "&_lastUpdated=%3C"
+ new InstantDt(new Date(time3)).getValueAsString());
+ new InstantDt(new Date(time3)).getValueAsString());
response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
@ -1264,24 +1281,24 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IdDt o2id = (IdDt) ourClient.create().resource(o2).execute().getId().toUnqualifiedVersionless();
Bundle actual = ourClient.search()
.forResource(Organization.class)
.withProfile("http://profile1")
.withProfile("http://profileX")
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.forResource(Organization.class)
.withProfile("http://profile1")
.withProfile("http://profileX")
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
assertEquals("nothing matches profile x", Collections.emptyList(), actual.getEntry());
actual = ourClient.search()
.forResource(Organization.class)
.withProfile("http://profile1")
.withProfile("http://profile2")
.returnBundle(Bundle.class)
.encodedJson()
.prettyPrint()
.execute();
.forResource(Organization.class)
.withProfile("http://profile1")
.withProfile("http://profile2")
.returnBundle(Bundle.class)
.encodedJson()
.prettyPrint()
.execute();
Set<String> expectedIds = new HashSet<String>();
expectedIds.add(o1id.getIdPart());
@ -1292,13 +1309,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals("Expects to retrieve the 1 orgination matching on Org1's profiles", expectedIds, actualIds);
actual = ourClient.search()
.forResource(Organization.class)
.withProfile("http://profile1")
.withAnyProfile(Arrays.asList("http://profile3", "http://profile2"))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.forResource(Organization.class)
.withProfile("http://profile1")
.withAnyProfile(Arrays.asList("http://profile3", "http://profile2"))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
expectedIds = new HashSet<String>();
expectedIds.add(o1id.getIdPart());
@ -1346,7 +1363,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
ourClient.update().resource(patient).execute();
ca.uhn.fhir.model.dstu2.resource.Bundle history = ourClient.history().onInstance(id).andReturnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class).prettyPrint().summaryMode(SummaryEnum.DATA)
.execute();
.execute();
assertEquals(3, history.getEntry().size());
assertEquals(id.withVersion("3"), history.getEntry().get(0).getResource().getId());
assertEquals(1, ((Patient) history.getEntry().get(0).getResource()).getName().size());
@ -1367,23 +1384,23 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IGenericClient client = ourClient;
int initialSize = client
.search()
.forResource(ImagingStudy.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(ImagingStudy.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/imagingstudy.json"), StandardCharsets.UTF_8);
client.create().resource(resBody).execute();
int newSize = client
.search()
.forResource(ImagingStudy.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
.search()
.forResource(ImagingStudy.class)
.returnBundle(Bundle.class)
.execute()
.getEntry()
.size();
assertEquals(1, newSize - initialSize);
@ -1397,14 +1414,14 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
//@formatter:off
String input = "<Parameters>\n" +
" <meta>\n" +
" <tag>\n" +
" <system value=\"http://example.org/codes/tags\"/>\n" +
" <code value=\"record-lost\"/>\n" +
" <display value=\"Patient File Lost\"/>\n" +
" </tag>\n" +
" </meta>\n" +
"</Parameters>";
" <meta>\n" +
" <tag>\n" +
" <system value=\"http://example.org/codes/tags\"/>\n" +
" <code value=\"record-lost\"/>\n" +
" <display value=\"Patient File Lost\"/>\n" +
" </tag>\n" +
" </meta>\n" +
"</Parameters>";
//@formatter:on
HttpPost post = new HttpPost(ourServerBase + "/Patient/" + id.getIdPart() + "/$meta-add");
@ -1471,6 +1488,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testPagingOverEverythingSet() throws InterruptedException {
Patient p = new Patient();
@ -1488,6 +1506,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(10);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(true);
StopWatch sw = new StopWatch();
ca.uhn.fhir.model.dstu2.resource.Bundle response = ourClient
.operation()
.onInstance(new IdDt(pid))
@ -1498,7 +1517,9 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
.execute();
assertEquals(10, response.getEntry().size());
assertEquals(null, response.getTotalElement().getValueAsString());
if (ourConnectionPoolSize > 1) {
assertEquals("Total should be null but was " + response.getTotalElement().getValueAsString() + " in " + sw.toString(), null, response.getTotalElement().getValueAsString());
}
assertThat(response.getLink("next").getUrl(), not(emptyString()));
// Load page 2
@ -1571,21 +1592,21 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
{
Bundle returned = ourClient
.search()
.forResource(Patient.class)
.returnBundle(Bundle.class)
.encodedXml()
.execute();
.search()
.forResource(Patient.class)
.returnBundle(Bundle.class)
.encodedXml()
.execute();
assertThat(returned.getEntry().size(), greaterThan(1));
assertEquals(ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum.SEARCH_RESULTS, returned.getTypeElement().getValueAsEnum());
}
{
Bundle returned = ourClient
.search()
.forResource(Patient.class)
.encodedJson()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.encodedJson()
.returnBundle(Bundle.class)
.execute();
assertThat(returned.getEntry().size(), greaterThan(1));
}
}
@ -1633,12 +1654,12 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSaveAndRetrieveWithContained01</td>"));
Bundle b = ourClient
.search()
.forResource("Patient")
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system:rpdstu2", "testSaveAndRetrieveWithContained01"))
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource("Patient")
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system:rpdstu2", "testSaveAndRetrieveWithContained01"))
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
assertEquals(1, b.getEntry().size());
}
@ -1708,13 +1729,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
//@formatter:off
ca.uhn.fhir.model.dstu2.resource.Bundle actual = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testSearchByIdentifier01"))
.encodedJson()
.prettyPrint()
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testSearchByIdentifier01"))
.encodedJson()
.prettyPrint()
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
//@formatter:on
assertEquals(1, actual.getEntry().size());
@ -1731,13 +1752,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IdDt p1Id = (IdDt) ourClient.create().resource(p1).execute().getId();
Bundle actual = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01"))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01"))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
@ -1765,12 +1786,12 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IdDt p2Id = (IdDt) ourClient.create().resource(p2).execute().getId();
Bundle actual = ourClient.search()
.forResource(Patient.class)
.where(Patient.ORGANIZATION.hasAnyOfIds(Arrays.asList(o1id.getIdPart(), o2id.getIdPart())))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.forResource(Patient.class)
.where(Patient.ORGANIZATION.hasAnyOfIds(Arrays.asList(o1id.getIdPart(), o2id.getIdPart())))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
Set<String> expectedIds = new HashSet<String>();
expectedIds.add(p1Id.getIdPart());
@ -1796,23 +1817,23 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
IdDt p1Id = (IdDt) ourClient.create().resource(p1).execute().getId();
Bundle actual = ourClient.search()
.forResource(Patient.class)
.where(Patient.ORGANIZATION.hasId(o1id.getIdPart()))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.forResource(Patient.class)
.where(Patient.ORGANIZATION.hasId(o1id.getIdPart()))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
actual = ourClient
.search()
.forResource(Patient.class)
.where(Patient.ORGANIZATION.hasId(o1id.getValue()))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.where(Patient.ORGANIZATION.hasId(o1id.getValue()))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
@ -1857,44 +1878,44 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
ourLog.info("Before: {}", beforeAny.getValue());
{
Bundle found = ourClient
.search()
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(beforeAny, null))
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(beforeAny, null))
.returnBundle(Bundle.class)
.execute();
List<IdDt> patients = toIdListUnqualifiedVersionless(found);
assertThat(patients, hasItems(id1a, id1b, id2));
}
{
Bundle found = ourClient.search()
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.returnBundle(Bundle.class)
.execute();
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.returnBundle(Bundle.class)
.execute();
List<IdDt> patients = toIdListUnqualifiedVersionless(found);
assertThat(patients, hasItems(id1a, id1b, id2));
}
{
Bundle found = ourClient.search()
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(beforeR2, null))
.returnBundle(Bundle.class)
.execute();
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(beforeR2, null))
.returnBundle(Bundle.class)
.execute();
List<IdDt> patients = toIdListUnqualifiedVersionless(found);
assertThat(patients, hasItems(id2));
assertThat(patients, not(hasItems(id1a, id1b)));
}
{
Bundle found = ourClient.search()
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(beforeAny, beforeR2))
.returnBundle(Bundle.class)
.execute();
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(beforeAny, beforeR2))
.returnBundle(Bundle.class)
.execute();
List<IdDt> patients = toIdListUnqualifiedVersionless(found);
assertThat(patients.toString(), patients, not(hasItems(id2)));
@ -1902,11 +1923,11 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
{
Bundle found = ourClient.search()
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(null, beforeR2))
.returnBundle(Bundle.class)
.execute();
.forResource(Patient.class)
.where(Patient.NAME.matches().value("testSearchLastUpdatedParamRp"))
.lastUpdated(new DateRangeParam(null, beforeR2))
.returnBundle(Bundle.class)
.execute();
List<IdDt> patients = toIdListUnqualifiedVersionless(found);
assertThat(patients, (hasItems(id1a, id1b)));
@ -1951,7 +1972,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertThat(matches, greaterThan(0));
}
@Test
public void testSearchReturnsSearchDate() throws Exception {
ourLog.info("Starting testSearchReturnsSearchDate");
@ -1960,11 +1981,11 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
Thread.sleep(100);
ca.uhn.fhir.model.dstu2.resource.Bundle found = ourClient
.search()
.forResource(Patient.class)
.prettyPrint()
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.prettyPrint()
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.execute();
Thread.sleep(100);
Date after = new Date();
@ -1978,7 +1999,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertTrue(value.after(before));
assertTrue(value.before(after));
}
@Test
public void testSearchWithInclude() throws Exception {
Organization org = new Organization();
@ -1991,13 +2012,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
ourClient.create().resource(pat).prettyPrint().encodedXml().execute().getId();
Bundle found = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system:rpdstu2","testSearchWithInclude02"))
.include(Patient.INCLUDE_ORGANIZATION)
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndIdentifier("urn:system:rpdstu2", "testSearchWithInclude02"))
.include(Patient.INCLUDE_ORGANIZATION)
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
assertEquals(2, found.getEntry().size());
assertEquals(Patient.class, found.getEntry().get(0).getResource().getClass());
@ -2054,13 +2075,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
{
Bundle found = ourClient
.search()
.forResource(Organization.class)
.where(Organization.NAME.isMissing(false))
.count(100)
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Organization.class)
.where(Organization.NAME.isMissing(false))
.count(100)
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
List<IdDt> list = toIdListUnqualifiedVersionless(found);
ourLog.info(methodName + ": " + list.toString());
@ -2071,13 +2092,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
Bundle found = ourClient
.search()
.forResource(Organization.class)
.where(Organization.NAME.isMissing(true))
.count(100)
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Organization.class)
.where(Organization.NAME.isMissing(true))
.count(100)
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
List<IdDt> list = toIdListUnqualifiedVersionless(found);
ourLog.info(methodName + " found: " + list.toString() + " - Wanted " + orgMissing + " but not " + orgNotMissing);
@ -2094,7 +2115,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
checkParamMissing(Observation.SP_ENCOUNTER);
checkParamMissing(Observation.SP_DATE);
}
@Test
public void testSearchWithTextInexactMatch() throws Exception {
Observation obs = new Observation();
@ -2295,7 +2316,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
CloseableHttpResponse resp = ourHttpClient.execute(post);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
String output= IOUtils.toString(resp.getEntity().getContent());
String output = IOUtils.toString(resp.getEntity().getContent());
ourLog.info(output);
} finally {
resp.close();
@ -2387,7 +2408,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
response.close();
}
pt.addName().addFamily(methodName+"2");
pt.addName().addFamily(methodName + "2");
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut put = new HttpPut(ourServerBase + "/Patient?name=" + methodName);
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
@ -2493,7 +2514,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@Test
public void testUpdateWithClientSuppliedIdWhichDoesntExist() {
Patient p1 = new Patient();
@ -2505,13 +2526,13 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertThat(p1Id.getValue(), containsString("Patient/testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2/_history"));
Bundle actual = ourClient
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2"))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
.search()
.forResource(Patient.class)
.where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2"))
.encodedJson()
.prettyPrint()
.returnBundle(Bundle.class)
.execute();
assertEquals(1, actual.getEntry().size());
assertEquals(p1Id.getIdPart(), actual.getEntry().get(0).getResource().getId().getIdPart());
@ -2578,7 +2599,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
/**
* From a Skype message from Brian Postlethwaite
*/
@ -2725,18 +2746,18 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertThat(resp,
stringContainsInOrder("<ValueSet xmlns=\"http://hl7.org/fhir\">",
"<expansion>",
"<contains>",
"<system value=\"http://loinc.org\"/>",
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>",
"</contains>",
"<contains>",
"<system value=\"http://loinc.org\"/>",
"<code value=\"8450-9\"/>",
"<display value=\"Systolic blood pressure--expiration\"/>",
"</contains>",
"<contains>",
"<system value=\"http://loinc.org\"/>",
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>",
"</contains>",
"<contains>",
"<system value=\"http://loinc.org\"/>",
"<code value=\"8450-9\"/>",
"<display value=\"Systolic blood pressure--expiration\"/>",
"</contains>",
"</expansion>"
));
));
//@formatter:on
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
@ -2755,8 +2776,8 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, response.getStatusLine().getStatusCode());
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"));
//@formatter:on
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
@ -2775,9 +2796,9 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
assertEquals(200, response.getStatusLine().getStatusCode());
//@formatter:off
assertThat(resp, stringContainsInOrder(
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"
));
"<code value=\"11378-7\"/>",
"<display value=\"Systolic blood pressure at First encounter\"/>"
));
//@formatter:on
} finally {
IOUtils.closeQuietly(response.getEntity().getContent());
@ -2785,7 +2806,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
}
}
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();

View File

@ -11,14 +11,12 @@ import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import org.hl7.fhir.r4.model.UriType;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.util.AopTestUtils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@ -102,16 +100,14 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
.addTarget()
.setCode("34567");
runInTransaction(() -> {
try {
runInTransaction(() -> {
myConceptMapDao.create(conceptMap);
});
fail();
} catch (UnprocessableEntityException e) {
assertEquals("ConceptMap has no value for ConceptMap.url", e.getMessage());
}
});
try {
runInTransaction(() -> {
myConceptMapDao.create(conceptMap);
});
fail();
} catch (UnprocessableEntityException e) {
assertEquals("ConceptMap has no value for ConceptMap.url", e.getMessage());
}
}

View File

@ -187,8 +187,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>

View File

@ -138,8 +138,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>

View File

@ -55,8 +55,8 @@
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>
@ -65,8 +65,8 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
</dependency>
<dependency>

View File

@ -87,8 +87,8 @@ public class FhirTesterConfig {
.addServer()
.withId("spark2")
.withFhirVersion(FhirVersionEnum.DSTU2)
.withBaseUrl("http://spark-dstu2.furore.com/fhir")
.withName("Spark - Furore (DSTU2 FHIR)");
.withBaseUrl("http://vonk.furore.com/")
.withName("Vonk - Furore (STU3 FHIR)");
return retVal;
}

View File

@ -72,8 +72,8 @@
<artifactId>thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>
@ -82,8 +82,8 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
</dependency>
<dependency>
@ -197,8 +197,8 @@
com.ctc.wstx.api;version="4.4";resolution:=optional,
com.ctc.wstx.*;version="4.4";resolution:=optional,
com.google.*;resolution:=optional;-remove-attribute:=version,
com.phloc.commons;resolution:=optional;-remove-attribute:=version,
com.phloc.*;resolution:=optional;-remove-attribute:=version,
com.helger.commons;resolution:=optional;-remove-attribute:=version,
com.helger.*;resolution:=optional;-remove-attribute:=version,
javassist;-remove-attribute:=version,
javax.*;-remove-attribute:=version,
net.sf.saxon;resolution:=optional,

View File

@ -68,13 +68,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>

View File

@ -130,22 +130,6 @@
<artifactId>thymeleaf</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<scope>test</scope>
<exclusions><!--
<exclusion>
<artifactId>Saxon-HE</artifactId>
<groupId>net.sf.saxon</groupId>
</exclusion>-->
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<scope>test</scope>
</dependency>
<!-- UNIT TEST DEPENDENCIES -->
@ -208,6 +192,16 @@
<artifactId>spring-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<reporting>

View File

@ -11,6 +11,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import com.helger.commons.io.stream.StringInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.*;
@ -29,7 +30,6 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.google.common.base.Charsets;
import com.phloc.commons.io.streams.StringInputStream;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
@ -83,7 +83,7 @@ public class GenericClientDstu2_1Test {
return body;
}
private ArgumentCaptor<HttpUriRequest> prepareClientForSearchResponse() throws IOException, ClientProtocolException {
private ArgumentCaptor<HttpUriRequest> prepareClientForSearchResponse() throws IOException {
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -92,7 +92,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -111,7 +111,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -149,7 +149,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -187,7 +187,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -225,7 +225,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -264,7 +264,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -303,7 +303,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -330,7 +330,7 @@ public class GenericClientDstu2_1Test {
}
@Test
public void testPatchInvalid() throws Exception {
public void testPatchInvalid() {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
try {
@ -354,7 +354,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -398,7 +398,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -441,7 +441,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -505,7 +505,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -537,14 +537,14 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
if (myAnswerCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8"));
} else {
@ -586,14 +586,14 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
myAnswerCount++;
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8"));
}
@ -625,7 +625,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -652,7 +652,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -697,7 +697,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -737,7 +737,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -773,7 +773,7 @@ public class GenericClientDstu2_1Test {
private int myCount = 0;
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
final String respString;
if (myCount == 1 || myCount == 2) {
ourLog.info("Encoding patient");
@ -822,7 +822,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
final String respString;
if (myAnswerCount >= 1) {
ourLog.info("Encoding patient");
@ -872,7 +872,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
final String respString;
if (myAnswerCount >= 1) {
ourLog.info("Encoding patient");
@ -912,7 +912,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public StringInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public StringInputStream answer(InvocationOnMock theInvocation) {
return new StringInputStream("HELLO", Charsets.UTF_8);
}
});
@ -937,7 +937,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public StringInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public StringInputStream answer(InvocationOnMock theInvocation) {
return new StringInputStream("not implemented", Charsets.UTF_8);
}
});
@ -968,7 +968,7 @@ public class GenericClientDstu2_1Test {
.forResource(Patient.class)
.where(Patient.FAMILY.matches().value((String) null))
.and(Patient.BIRTHDATE.exactly().day((Date) null))
.and(Patient.GENDER.exactly().code((String) null))
.and(Patient.GENDER.exactly().code(null))
.and(Patient.ORGANIZATION.hasId((String) null))
.returnBundle(Bundle.class)
.execute();
@ -1019,7 +1019,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(encoded), Charset.forName("UTF-8"));
}
});
@ -1064,7 +1064,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(encoded), Charset.forName("UTF-8"));
}
});
@ -1121,7 +1121,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(null);
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1152,7 +1152,7 @@ public class GenericClientDstu2_1Test {
// when(myHttpResponse.getEntity().getContentType()).thenReturn(null);
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1179,7 +1179,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1286,7 +1286,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1405,7 +1405,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1497,7 +1497,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1564,7 +1564,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1601,7 +1601,7 @@ public class GenericClientDstu2_1Test {
}
@Test
public void testTransactionWithInvalidBody() throws Exception {
public void testTransactionWithInvalidBody() {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
// Transaction
@ -1652,7 +1652,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1691,14 +1691,14 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
if (myAnswerCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8"));
} else {
@ -1739,14 +1739,14 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
myAnswerCount++;
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8"));
}
@ -1784,7 +1784,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1821,7 +1821,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1842,7 +1842,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1870,14 +1870,14 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] {};
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8"));
}
});
@ -1910,7 +1910,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1948,7 +1948,7 @@ public class GenericClientDstu2_1Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});

View File

@ -103,13 +103,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope><!-- <exclusions> <exclusion> <artifactId>Saxon-HE</artifactId> <groupId>net.sf.saxon</groupId> </exclusion> </exclusions> -->
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>

View File

@ -28,7 +28,7 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
import com.phloc.commons.collections.iterate.ArrayEnumeration;
import com.helger.collection.iterate.ArrayEnumeration;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
@ -130,7 +130,7 @@ public class ResponseHighlightingInterceptorTest {
when(req.getHeaders(Constants.HEADER_ACCEPT)).thenAnswer(new Answer<Enumeration<String>>() {
@Override
public Enumeration<String> answer(InvocationOnMock theInvocation) throws Throwable {
return new ArrayEnumeration<String>("text/html,application/xhtml+xml,application/xml;q=0.9");
return new ArrayEnumeration<>("text/html,application/xhtml+xml,application/xml;q=0.9");
}
});
when(req.getHeader(Constants.HEADER_ORIGIN)).thenAnswer(new Answer<String>() {

View File

@ -217,13 +217,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>

View File

@ -11,6 +11,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import com.helger.commons.io.stream.StringInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.*;
@ -29,7 +30,6 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.google.common.base.Charsets;
import com.phloc.commons.io.streams.StringInputStream;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;

View File

@ -122,8 +122,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
@ -133,8 +133,8 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>

View File

@ -125,13 +125,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>
@ -192,11 +192,6 @@
<artifactId>spring-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<reporting>

View File

@ -6,13 +6,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import org.apache.commons.codec.Charsets;
import org.apache.commons.lang3.StringUtils;
@ -250,7 +244,7 @@ public abstract class BaseWorkerContext implements IWorkerContext {
return laterVersion(newParts[i], oldParts[i]);
}
// This should never happen
throw new Error("Delimited versions have exact match for delimiter '"+delimiter+"' : "+newParts+" vs "+oldParts);
throw new Error("Delimited versions have exact match for delimiter '"+delimiter+"' : "+ Arrays.asList(newParts)+" vs "+Arrays.asList(oldParts));
}
protected <T extends MetadataResource> void seeMetadataResource(T r, Map<String, T> map, boolean addId) throws FHIRException {
@ -1045,6 +1039,8 @@ public abstract class BaseWorkerContext implements IWorkerContext {
return (T) maps.get(uri);
if (transforms.containsKey(uri))
return (T) transforms.get(uri);
if (questionnaires.containsKey(uri))
return (T) questionnaires.get(uri);
return null;
} else if (class_ == StructureDefinition.class) {
return (T) structures.get(uri);
@ -1052,6 +1048,8 @@ public abstract class BaseWorkerContext implements IWorkerContext {
return (T) valueSets.get(uri);
} else if (class_ == CodeSystem.class) {
return (T) codeSystems.get(uri);
} else if (class_ == ConceptMap.class) {
return (T) maps.get(uri);
} else if (class_ == OperationDefinition.class) {
OperationDefinition od = operations.get(uri);
return (T) od;
@ -1069,7 +1067,7 @@ public abstract class BaseWorkerContext implements IWorkerContext {
}
}
if (class_ == Questionnaire.class)
return null;
return (T) questionnaires.get(uri);
if (class_ == null) {
if (uri.matches(Constants.URI_REGEX) && !uri.contains("ValueSet"))
return null;

View File

@ -1,10 +1,11 @@
package org.hl7.fhir.r4.utils;
//import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.util.ElementUtil;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.http.protocol.ExecutionContext;
import org.fhir.ucum.Decimal;
import org.fhir.ucum.Pair;
import org.fhir.ucum.UcumException;
@ -24,8 +25,13 @@ import org.hl7.fhir.r4.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails;
import org.hl7.fhir.utilities.Utilities;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.length;
/**
*
* @author Grahame Grieve
@ -731,7 +737,7 @@ public class FHIRPathEngine {
String s = lexer.take();
if (s.equals("year") || s.equals("years"))
ucum = "a";
else if (s.equals("month") || s.equals("month"))
else if (s.equals("month") || s.equals("months"))
ucum = "mo";
else if (s.equals("week") || s.equals("weeks"))
ucum = "wk";
@ -2072,8 +2078,9 @@ public class FHIRPathEngine {
result.add(item);
} else
getChildrenByName(item, exp.getName(), result);
// todo: GG 1st April 201 - why do this?
if (result.size() == 0 && atEntry && context.appInfo != null) {
// well, we didn't get a match on the name - we'll see if the name matches a constant known by the context.
// (if the name does match, and the user wants to get the constant value, they'll have to try harder...
Base temp = hostServices.resolveConstant(context.appInfo, exp.getName());
if (temp != null) {
result.add(temp);
@ -3280,7 +3287,7 @@ public class FHIRPathEngine {
return Quantity.fromUcum(v, s.substring(1, s.length()-1));
if (s.equals("year") || s.equals("years"))
return Quantity.fromUcum(v, "a");
else if (s.equals("month") || s.equals("month"))
else if (s.equals("month") || s.equals("months"))
return Quantity.fromUcum(v, "mo");
else if (s.equals("week") || s.equals("weeks"))
return Quantity.fromUcum(v, "wk");

View File

@ -17,6 +17,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import com.helger.commons.io.stream.StringInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.*;
@ -36,7 +37,6 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.google.common.base.Charsets;
import com.phloc.commons.io.streams.StringInputStream;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
@ -93,7 +93,7 @@ public class GenericClientR4Test {
return body;
}
private ArgumentCaptor<HttpUriRequest> prepareClientForSearchResponse() throws IOException, ClientProtocolException {
private ArgumentCaptor<HttpUriRequest> prepareClientForSearchResponse() throws IOException {
final String msg = "{\"resourceType\":\"Bundle\",\"id\":null,\"base\":\"http://localhost:57931/fhir/contextDev\",\"total\":1,\"link\":[{\"relation\":\"self\",\"url\":\"http://localhost:57931/fhir/contextDev/Patient?identifier=urn%3AMultiFhirVersionTest%7CtestSubmitPatient01&_format=json\"}],\"entry\":[{\"resource\":{\"resourceType\":\"Patient\",\"id\":\"1\",\"meta\":{\"versionId\":\"1\",\"lastUpdated\":\"2014-12-20T18:41:29.706-05:00\"},\"identifier\":[{\"system\":\"urn:MultiFhirVersionTest\",\"value\":\"testSubmitPatient01\"}]}}]}";
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
@ -102,7 +102,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -143,7 +143,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -187,7 +187,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -234,7 +234,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -278,7 +278,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -322,7 +322,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -366,7 +366,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -408,7 +408,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -472,7 +472,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -504,14 +504,14 @@ public class GenericClientR4Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
if (myAnswerCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8"));
} else {
@ -553,14 +553,14 @@ public class GenericClientR4Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
myAnswerCount++;
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8"));
}
@ -592,7 +592,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -619,7 +619,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -664,7 +664,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -704,7 +704,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -740,7 +740,7 @@ public class GenericClientR4Test {
private int myCount = 0;
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
final String respString;
if (myCount == 1 || myCount == 2) {
ourLog.info("Encoding patient");
@ -788,7 +788,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
final String respString;
if (myAnswerCount >= 1) {
ourLog.info("Encoding patient");
@ -828,7 +828,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public StringInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public StringInputStream answer(InvocationOnMock theInvocation) {
return new StringInputStream("HELLO", Charsets.UTF_8);
}
});
@ -853,7 +853,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public StringInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public StringInputStream answer(InvocationOnMock theInvocation) {
return new StringInputStream("not implemented", Charsets.UTF_8);
}
});
@ -884,7 +884,7 @@ public class GenericClientR4Test {
.forResource(Patient.class)
.where(Patient.FAMILY.matches().value((String) null))
.and(Patient.BIRTHDATE.exactly().day((Date) null))
.and(Patient.GENDER.exactly().code((String) null))
.and(Patient.GENDER.exactly().code(null))
.and(Patient.ORGANIZATION.hasId((String) null))
.returnBundle(Bundle.class)
.execute();
@ -915,7 +915,7 @@ public class GenericClientR4Test {
}
@Test
public void testPatchInvalid() throws Exception {
public void testPatchInvalid() {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
try {
@ -941,7 +941,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -980,7 +980,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1019,7 +1019,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1057,7 +1057,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1095,7 +1095,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1133,7 +1133,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1180,7 +1180,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON_NEW + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(encoded), Charset.forName("UTF-8"));
}
});
@ -1225,7 +1225,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(encoded), Charset.forName("UTF-8"));
}
});
@ -1282,7 +1282,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(null);
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1313,7 +1313,7 @@ public class GenericClientR4Test {
// when(myHttpResponse.getEntity().getContentType()).thenReturn(null);
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1331,7 +1331,7 @@ public class GenericClientR4Test {
}
@Test
public void testRevIncludeRecursive() throws ClientProtocolException, IOException {
public void testRevIncludeRecursive() throws IOException {
ArgumentCaptor<HttpUriRequest> capt = prepareClientForSearchResponse();
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
@ -1361,7 +1361,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1468,7 +1468,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1578,7 +1578,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1670,7 +1670,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1756,7 +1756,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).then(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
public InputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
}
});
@ -1793,7 +1793,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1830,7 +1830,7 @@ public class GenericClientR4Test {
}
@Test
public void testTransactionWithInvalidBody() throws Exception {
public void testTransactionWithInvalidBody() {
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
// Transaction
@ -1881,7 +1881,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -1920,14 +1920,14 @@ public class GenericClientR4Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
if (myAnswerCount++ == 0) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8"));
} else {
@ -1968,14 +1968,14 @@ public class GenericClientR4Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] { new BasicHeader(Constants.HEADER_LOCATION, "http://foo.com/base/Patient/222/_history/3") };
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
myAnswerCount++;
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp1)), Charset.forName("UTF-8"));
}
@ -2013,7 +2013,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -2050,7 +2050,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -2071,7 +2071,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -2099,14 +2099,14 @@ public class GenericClientR4Test {
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getAllHeaders()).thenAnswer(new Answer<Header[]>() {
@Override
public Header[] answer(InvocationOnMock theInvocation) throws Throwable {
public Header[] answer(InvocationOnMock theInvocation) {
return new Header[] {};
}
});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(p.encodeResourceToString(resp0)), Charset.forName("UTF-8"));
}
});
@ -2139,7 +2139,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});
@ -2177,7 +2177,7 @@ public class GenericClientR4Test {
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<ReaderInputStream>() {
@Override
public ReaderInputStream answer(InvocationOnMock theInvocation) throws Throwable {
public ReaderInputStream answer(InvocationOnMock theInvocation) {
return new ReaderInputStream(new StringReader(respString), Charset.forName("UTF-8"));
}
});

View File

@ -65,8 +65,8 @@
Schematron resource validation. Otherwise, they may be omitted.
-->
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<exclusions>
<exclusion>
<artifactId>Saxon-HE</artifactId>
@ -75,8 +75,8 @@
</exclusions>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<version>4.3.3</version>
</dependency>
@ -123,4 +123,4 @@
</plugins>
</build>
</project>
</project>

View File

@ -173,13 +173,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -89,9 +89,14 @@
<bundle dependency='true'>
mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xmlresolver/${servicemix_xmlresolver_version}
</bundle>
<bundle dependency="true">mvn:org.apache.aries.spifly/org.apache.aries.spifly.dynamic.bundle/${aries_spifly_version}</bundle>
<bundle dependency='true'>mvn:com.google.code.findbugs/jsr305/${jsr305_version}</bundle>
<bundle>mvn:com.phloc/phloc-schematron/${phloc_schematron_version}</bundle>
<bundle>mvn:com.phloc/phloc-commons/${phloc_commons_version}</bundle>
<bundle dependency='true'>mvn:com.helger/ph-commons/${ph_commons_version}</bundle>
<bundle dependency='true'>mvn:com.helger/ph-collection/${ph_commons_version}</bundle>
<bundle dependency='true'>mvn:com.helger/ph-xml/${ph_commons_version}</bundle>
<bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jaxb-impl/${jaxb_bundle_version}</bundle>
<bundle dependency='true'>mvn:com.helger/ph-jaxb/${ph_commons_version}</bundle>
<bundle dependency='true'>mvn:com.helger/ph-schematron/${ph_schematron_version}</bundle>
</feature>
<feature name='hapi-fhir-validation' version='${project.version}' start-level='50'>

View File

@ -14,7 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -98,6 +98,7 @@
<version>${project.version}</version>
</dependency>
<!-- karaf test -->
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
@ -122,6 +123,12 @@
<version>${apache_karaf_version}</version>
<scope>test</scope>
<type>tar.gz</type>
<exclusions>
<exclusion>
<groupId>org.ops4j.pax.logging</groupId>
<artifactId>pax-logging-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>

View File

@ -0,0 +1,7 @@
package ca.uhn.fhir.tests.integration.karaf;
public class ValidationConstants {
public static final boolean SCHEMATRON_ENABLED = true;
}

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.tests.integration.karaf.ValidationConstants;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.SchemaBaseValidator;
import ca.uhn.fhir.validation.ValidationFailureException;
@ -85,7 +86,7 @@ public class Dstu2ResourceValidatorDstu2Test {
private FhirValidator createFhirValidator() {
FhirValidator val = ourCtx.newValidator();
val.setValidateAgainstStandardSchema(true);
val.setValidateAgainstStandardSchematron(true);
val.setValidateAgainstStandardSchematron(ValidationConstants.SCHEMATRON_ENABLED);
return val;
}
@ -156,7 +157,9 @@ public class Dstu2ResourceValidatorDstu2Test {
FhirValidator val = ourCtx.newValidator();
val.setValidateAgainstStandardSchema(true);
val.setValidateAgainstStandardSchematron(false);
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
val.validate(p);
@ -246,7 +249,9 @@ public class Dstu2ResourceValidatorDstu2Test {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
ValidationResult result = val.validateWithResult(messageString);
@ -299,7 +304,9 @@ public class Dstu2ResourceValidatorDstu2Test {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
ValidationResult result = val.validateWithResult(messageString);

View File

@ -6,19 +6,12 @@ import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.tests.integration.karaf.ValidationConstants;
import ca.uhn.fhir.validation.*;
import ca.uhn.fhir.validation.schematron.SchematronBaseValidator;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.Validate;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
@ -33,14 +26,10 @@ import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.HAPI_FHIR_VALIDATION_DSTU3;
import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.KARAF;
import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.WRAP;
import static ca.uhn.fhir.tests.integration.karaf.PaxExamOptions.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.when;
import static org.ops4j.pax.exam.CoreOptions.*;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.debugConfiguration;
/**
@ -145,7 +134,9 @@ public class ResourceValidatorDstu3FeatureTest {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult output = val.validateWithResult(p);
@ -162,7 +153,9 @@ public class ResourceValidatorDstu3FeatureTest {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult output = val.validateWithResult(p);
@ -232,7 +225,9 @@ public class ResourceValidatorDstu3FeatureTest {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(q);
@ -273,7 +268,9 @@ public class ResourceValidatorDstu3FeatureTest {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(encoded);
@ -321,7 +318,9 @@ public class ResourceValidatorDstu3FeatureTest {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(messageString);
@ -374,7 +373,9 @@ public class ResourceValidatorDstu3FeatureTest {
FhirValidator val = ourCtx.newValidator();
val.registerValidatorModule(new SchemaBaseValidator(ourCtx));
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
if (ValidationConstants.SCHEMATRON_ENABLED) {
val.registerValidatorModule(new SchematronBaseValidator(ourCtx));
}
val.registerValidatorModule(new FhirInstanceValidator());
ValidationResult result = val.validateWithResult(messageString);

89
pom.xml
View File

@ -51,7 +51,20 @@
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!--
Snapshots should generally not be needed
<repository>
<id>oss-snapshot</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
-->
</repositories>
<description>
@ -444,16 +457,17 @@
<!-- Dependency Versions -->
<apache_karaf_version>4.1.4</apache_karaf_version>
<aries_spifly_version>1.0.10</aries_spifly_version>
<caffeine_version>2.6.2</caffeine_version>
<commons_codec_version>1.10</commons_codec_version>
<commons_io_version>2.5</commons_io_version>
<commons_lang3_version>3.6</commons_lang3_version>
<derby_version>10.14.1.0</derby_version>
<derby_version>10.14.2.0</derby_version>
<error_prone_annotations_version>2.0.18</error_prone_annotations_version>
<guava_version>23.0</guava_version>
<gson_version>2.8.1</gson_version>
<jaxb_api_version>2.3.0</jaxb_api_version>
<jaxb_core_version>2.3.0</jaxb_core_version>
<jaxb_runtime_version>2.3.0</jaxb_runtime_version>
<jersey_version>2.25.1</jersey_version>
<jetty_version>9.4.8.v20171121</jetty_version>
<jsr305_version>3.0.2</jsr305_version>
@ -464,11 +478,12 @@
<hibernate_search_version>5.7.1.Final</hibernate_search_version>
<httpcore_version>4.4.6</httpcore_version>
<httpclient_version>4.5.3</httpclient_version>
<jaxb_bundle_version>2.2.11_1</jaxb_bundle_version>
<lucene_version>5.5.4</lucene_version>
<maven_assembly_plugin_version>2.5.3</maven_assembly_plugin_version>
<maven_license_plugin_version>1.8</maven_license_plugin_version>
<phloc_schematron_version>2.7.1</phloc_schematron_version>
<phloc_commons_version>4.4.11</phloc_commons_version>
<ph_schematron_version>5.0.4</ph_schematron_version>
<ph_commons_version>9.1.1</ph_commons_version>
<servicemix_saxon_version>9.5.1-5_1</servicemix_saxon_version>
<servicemix_xmlresolver_version>1.2_5</servicemix_xmlresolver_version>
<spring_version>5.0.3.RELEASE</spring_version>
@ -572,14 +587,14 @@
<version>23.0</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<version>${ph_schematron_version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<version>${ph_commons_version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
@ -601,6 +616,11 @@
<artifactId>commons-codec</artifactId>
<version>${commons_codec_version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
@ -658,16 +678,6 @@
<artifactId>gson</artifactId>
<version>${gson_version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>${jaxb_core_version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb_core_version}</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
@ -952,6 +962,11 @@
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>${jaxb_runtime_version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
@ -1182,6 +1197,11 @@
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@ -1251,7 +1271,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<version>2.20</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -1278,7 +1298,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
<version>2.21.0</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<runOrder>random</runOrder>
@ -1509,24 +1529,29 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-java</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[1.8,)</version>
<message>
The hapi-fhir Maven build requires JDK version 1.8 or higher.
</message>
</requireJavaVersion>
</rules>
</configuration>
</execution>
</executions>
<configuration>
<rules>
<requireMavenVersion>
<version>3.5</version>
</requireMavenVersion>
<requireJavaVersion>
<!--<version>[1.8,)</version>-->
<version>1.8</version>
<message>
The hapi-fhir Maven build requires JDK version 1.8.x.
</message>
</requireJavaVersion>
</rules>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>

View File

@ -162,6 +162,11 @@
an unspecified error was thrown by the JPA server. An HTTP 409
(Conflict) with an informative error message is now thrown.
</action>
<action type="fix">
A bug in the JPA server's DSTU2 transaction processing routine caused it
to occasionally consume two database connections, which could lead to deadlocks
under heavy load. This has been fixed.
</action>
</release>
<release version="3.3.0" date="2018-03-29">
<action type="add">

View File

@ -1,135 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Command Line Tool</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Command Line Tool for HAPI FHIR">
<p>
<b>hapi-fhir-cli</b> is the HAPI FHIR Command Line tool. It features a number of HAPI's
built-in features as easy to use command line options.
</p>
<subsection name="Download and Installation">
<p>
You can get the tool by downloading it from our
<a href="https://github.com/jamesagnew/hapi-fhir/releases">GitHub Releases</a> page
(look for the archive named <code>hapi-fhir-[version]-cli.tar.bz2</code> on OSX/Linux or <code>hapi-fhir-[version]-cli.zip</code> on Windows).
</p>
<p>
When you have downloaded the archive (either ZIP or tar.bz2), expand it into a directory
where you will keep it, and add this directory to your path.
</p>
<p>
You can now try the tool out by executing the following command: <code>hapi-fhir-cli</code>
</p>
<p>
This command should show a help screen, as shown in the screeenshot below.
</p>
<img src="./images/hapi-fhir-cli.png" alt="Basic screen shot" style="margin-left: 40px;"/>
</subsection>
<subsection name="Troubleshooting">
<p>
<b>Note on Java version support:</b> The HAPI library is designed to
work in Java 6+, but the Command Line Tool required a minimum of Java 8. This
is because the Jetty Web Server that is used within the tool has this requirement.
</p>
<p>
The tool should work correctly on any system that has Java 8 (or newer) installed. If
it is not working correctly, first try the following command to test if Java is installed:<br/>
<code>$ java -version</code>
</p>
<p>
If this command does not produce output similar to the following, you should install/reinstall
Java.<br/>
<pre><![CDATA[$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)]]></pre>
</p>
<p>
If this does not help, please post a question on our
<a href="https://groups.google.com/d/forum/hapi-fhir">Google Group</a>.
</p>
</subsection>
</section>
<section name="Server (run-server)">
<p>
The CLI tool can be used to start a local, fully functional FHIR server which you can use
for testing. To start this server, simply issue the command <code>hapi-fhir-cli run-server</code>
as shown in the example below:
</p>
<img src="./images/hapi-fhir-cli-run-server.png" alt="Run Server" style="margin-left: 40px;"/>
<p>
Once the server has started, you can access the testing webpage by pointing your
browser at <a href="http://localhost:8080/">http://localhost:8080/</a>. The FHIR
server base URL will be <a href="http://localhost:8080/baseDstu2/">http://localhost:8080/baseDstu2/</a>.
</p>
<p>
Note that by default this server will not be populated with any resources at all. You can
easily populate it with the FHIR example resources by <b>leaving it running</b> and opening
a second terminal window, then using the <code>hapi-fhir-cli upload-examples</code> command
(see the section below).
</p>
<p>
The server uses a local Derby database instance for storage. You may want to execute
this command in an empty directory, which you can clear if you want to reset the server.
</p>
</section>
<section name="Upload Example Resources (upload-examples)">
<p>
The <b>upload-examples</b> command downloads the complete set of FHIR example resources from
the HL7 website, and uploads them to a server of your choice. This can be useful to
populate a server with test data.
</p>
<p>
To execute this command, uploading test resources to a local CLI server, issue
the following: <code>hapi-fhir-cli upload-examples -t http://localhost:8080/baseDstu2</code>
</p>
<p>
Note that this command may take a surprisingly long time to complete because of the
large number of examples.
</p>
</section>
<section name="Upload Terminology">
<p>
The HAPI FHIR JPA server has a terminology server, and has the ability to
be populated with "external" code systems. These code systems are systems
that contain large numbers of codes, so the codes are not stored directly
inside the resource body.
</p>
<p>
HAPI has methods for uploading several popular code systems into its tables
using the distribution files produced by the respective code systems. This
is done using the <code>upload-terminology</code> command. The following
examples show how to do this for several popular code systems.
</p>
<p>
Note that the path and exact filename of the terminology files will likely
need to be adjusted for your local disk structure.
</p>
<h4>
SNOMED CT
</h4>
<pre>./hapi-fhir-cli upload-terminology -d Downloads/SnomedCT_RF2Release_INT_20160131.zip -f dstu3 -t http://localhost:8080/baseDstu3 -u http://snomed.info/sct</pre>
<h4>LOINC</h4>
<pre>./hapi-fhir-cli upload-terminology -d Downloads/LOINC_2.54_MULTI-AXIAL_HIERARCHY.zip -d Downloads/LOINC_2.54_Text.zip -f dstu3 -t http://localhost:8080/baseDstu3 -u http://loinc.org</pre>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Command Line Tool</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Command Line Tool for HAPI FHIR">
<p>
<b>hapi-fhir-cli</b> is the HAPI FHIR Command Line tool. It features a number of HAPI's
built-in features as easy to use command line options.
</p>
<subsection name="Download and Installation">
<p>
You can get the tool by downloading it from our
<a href="https://github.com/jamesagnew/hapi-fhir/releases">GitHub Releases</a> page
(look for the archive named <code>hapi-fhir-[version]-cli.tar.bz2</code> on OSX/Linux or <code>hapi-fhir-[version]-cli.zip</code> on Windows).
</p>
<p>
When you have downloaded the archive (either ZIP or tar.bz2), expand it into a directory
where you will keep it, and add this directory to your path.
</p>
<p>
You can now try the tool out by executing the following command: <code>hapi-fhir-cli</code>
</p>
<p>
This command should show a help screen, as shown in the screeenshot below.
</p>
<img src="./images/hapi-fhir-cli.png" alt="Basic screen shot" style="margin-left: 40px;"/>
</subsection>
<subsection name="Download and Installation - Mac/OSX">
<p>
hapi-fhir-cli is available as a <a href="https://brew.sh/">Homebrew</a> package
for Mac. It can be installed using the following command:
</p>
<code>brew install hapi-fhir-cli</code>
</subsection>
<subsection name="Troubleshooting">
<p>
<b>Note on Java version support:</b> The HAPI library is designed to
work in Java 6+, but the Command Line Tool required a minimum of Java 8. This
is because the Jetty Web Server that is used within the tool has this requirement.
</p>
<p>
The tool should work correctly on any system that has Java 8 (or newer) installed. If
it is not working correctly, first try the following command to test if Java is installed:<br/>
<code>$ java -version</code>
</p>
<p>
If this command does not produce output similar to the following, you should install/reinstall
Java.<br/>
<pre><![CDATA[$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)]]></pre>
</p>
<p>
If this does not help, please post a question on our
<a href="https://groups.google.com/d/forum/hapi-fhir">Google Group</a>.
</p>
</subsection>
</section>
<section name="Server (run-server)">
<p>
The CLI tool can be used to start a local, fully functional FHIR server which you can use
for testing. To start this server, simply issue the command <code>hapi-fhir-cli run-server</code>
as shown in the example below:
</p>
<img src="./images/hapi-fhir-cli-run-server.png" alt="Run Server" style="margin-left: 40px;"/>
<p>
Once the server has started, you can access the testing webpage by pointing your
browser at <a href="http://localhost:8080/">http://localhost:8080/</a>. The FHIR
server base URL will be <a href="http://localhost:8080/baseDstu2/">http://localhost:8080/baseDstu2/</a>.
</p>
<p>
Note that by default this server will not be populated with any resources at all. You can
easily populate it with the FHIR example resources by <b>leaving it running</b> and opening
a second terminal window, then using the <code>hapi-fhir-cli upload-examples</code> command
(see the section below).
</p>
<p>
The server uses a local Derby database instance for storage. You may want to execute
this command in an empty directory, which you can clear if you want to reset the server.
</p>
</section>
<section name="Upload Example Resources (upload-examples)">
<p>
The <b>upload-examples</b> command downloads the complete set of FHIR example resources from
the HL7 website, and uploads them to a server of your choice. This can be useful to
populate a server with test data.
</p>
<p>
To execute this command, uploading test resources to a local CLI server, issue
the following: <code>hapi-fhir-cli upload-examples -t http://localhost:8080/baseDstu2</code>
</p>
<p>
Note that this command may take a surprisingly long time to complete because of the
large number of examples.
</p>
</section>
<section name="Upload Terminology">
<p>
The HAPI FHIR JPA server has a terminology server, and has the ability to
be populated with "external" code systems. These code systems are systems
that contain large numbers of codes, so the codes are not stored directly
inside the resource body.
</p>
<p>
HAPI has methods for uploading several popular code systems into its tables
using the distribution files produced by the respective code systems. This
is done using the <code>upload-terminology</code> command. The following
examples show how to do this for several popular code systems.
</p>
<p>
Note that the path and exact filename of the terminology files will likely
need to be adjusted for your local disk structure.
</p>
<h4>
SNOMED CT
</h4>
<pre>./hapi-fhir-cli upload-terminology -d Downloads/SnomedCT_RF2Release_INT_20160131.zip -f dstu3 -t http://localhost:8080/baseDstu3 -u http://snomed.info/sct</pre>
<h4>LOINC</h4>
<pre>./hapi-fhir-cli upload-terminology -d Downloads/LOINC_2.54_MULTI-AXIAL_HIERARCHY.zip -d Downloads/LOINC_2.54_Text.zip -f dstu3 -t http://localhost:8080/baseDstu3 -u http://loinc.org</pre>
</section>
</body>
</document>

View File

@ -1,288 +1,288 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Validation</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Validation">
<p>
HAPI supportes two types of validation, both of which are described in the
sections below.
</p>
<ul>
<li>
<b>Parser Validation</b>
is validation at runtime during the parsing
of a resource. It can be used to catch input data that is impossible to
fit into the HAPI data model. For
example, it can be used to throw exceptions
or display error messages if a resource being parsed contains elements for which
there are no appropriate fields in a HAPI data structure. This is useful in order to ensure
that no data is being lost during parsing, but is less comprehensive than resource validation
against raw text data.
</li>
<li>
<b>Resource Validation</b>
is validation of the raw or parsed resource against
the official FHIR validation rules (e.g. Schema/Schematron/Profile/StructureDefinition/ValueSet)
as well as against custom profiles which have been developed.
</li>
</ul>
</section>
<!-- Parser Validation -->
<section name="Parser Validation">
<p>
Parser validation is controlled by calling
<code>setParserErrorHandler(IParserErrorHandler)</code>
on
either the FhirContext or on individual parser instances. This method
takes an
<code>IParserErrorHandler</code>
, which is a callback that
will be invoked any time a parse issue is detected.
</p>
<p>
There are two implementations of
<code>IParserErrorHandler</code>
worth
mentioning. You can also supply your own implementation if you want.
</p>
<ul>
<li>
<a href="./apidocs/ca/uhn/fhir/parser/LenientErrorHandler.html">LenientErrorHandler</a>
logs any errors but does not abort parsing. By default this handler is used, and it
logs errors at "warning" level. It can also be configured to silently
ignore issues.
</li>
<li>
<a href="./apidocs/ca/uhn/fhir/parser/StrictErrorHandler.html">StrictErrorHandler</a>
throws a
<code>DataFormatException</code>
if any errors are detected.
</li>
</ul>
<p>
The following example shows how to configure a parser to use strict validation.
</p>
<macro name="snippet">
<param name="id" value="parserValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
<p>
You can also configure the error handler at the FhirContext level, which is useful
for clients.
</p>
<macro name="snippet">
<param name="id" value="clientValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
<p>
FhirContext level validators can also be useful on servers.
</p>
<macro name="snippet">
<param name="id" value="serverValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</section>
<!-- RESOURCE VALIDATION -->
<section name="Resource Validation">
<p>
HAPI provides a built-in and configurable mechanism for validating resources.
This mechanism is called the
<i>Resource Validator.</i>
</p>
<p>
The resource validator is an extendible and modular system, and you
can configure it in a number of ways in order to get the specific
type of validation you want to achieve.
</p>
<p>
The validator can be manually invoked at any time by creating a
validator and configuring it with one or more
<a href="./apidocs/ca/uhn/fhir/validation/IValidatorModule.html">IValidatorModule</a>
instances.
</p>
<macro name="snippet">
<param name="id" value="validationIntro" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</section>
<section name="Resource Validation Module: Schema/Schematron">
<p>
FHIR resource definitions are distributed with a set of XML schema files (XSD)
as well as a set of XML Schematron (SCH) files. These two sets of files are
complimentary to each other, meaning that in order to claim compliance to the
FHIR specification, your resources must validate against both sets.
</p>
<p>
The two sets of files are included with HAPI, and it uses them to perform
validation.
</p>
<subsection name="Preparation">
<p>
In order to use HAPI's Schematron support, a libaray called
<a href="https://code.google.com/p/phloc-schematron/">Phloc-Schematron</a>
is used, so this library must be added to your classpath (or Maven POM file, Gradle
file, etc.)
Note that this library is specified as an optional dependency
by HAPI FHIR
so you need to explicitly include it if you want to use this
functionality.
</p>
<p>
See
<a href="./download.html">Downloads</a>
for more information on how
to add it.
</p>
</subsection>
<subsection name="Validating a Resource">
<p>
To validate a resource instance, a new validator instance is requested
from the FHIR Context. This validator is then applied against
a specific resource
instance, as shown in the example below.
</p>
<macro name="snippet">
<param name="id" value="basicValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
<subsection name="Validating a Set of Files">
<p>
The following example shows how to load a set of resources from files
on disk and validate each one.
</p>
<macro name="snippet">
<param name="id" value="validateFiles" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
<a name="structure_definition_validation" />
</section>
<section name="Resource Validation (Profile/StructureDefinition)">
<p>
HAPI also supports validation against StructureDefinition
resources. This functionality uses the HL7 "InstanceValidator", which is able
to check a resource for conformance to FHIR profiles
(StructureDefinitions, ValueSets, and CodeSystems),
including validating fields, extensions, and codes for conformance to their given ValueSets.
</p>
<p>
StructureDefinition validation can be used to validate a resource against the
official structure definitions (produced by HL7) as well as against custom
definitions provided either by HL7 or by the user.
</p>
<p class="doc_info_bubble">
The instance validator is experimental in the DSTU2 mode, but has become very stable
and full-featured in DSTU3 mode. Use with caution when validating DSTU2 resources using
instance validator.
</p>
<subsection name="Preparation">
<p>
To use this functionality, you must add the following two dependencies
to your classpath (or Maven POM file, Gradle file, etc.):
</p>
<ul>
<li>
<!-- TODO: add search.maven.org links to these -->
<b>hapi-fhir-structures-hl7org-dstu2</b>
: This file contains the "reference implementation"
structures and tooling. You need to include it even if you are not using the RI model
(the StructureDefinition validation will work against HAPI structures as well)
</li>
<li>
<b>hapi-fhir-validation-resources-dstu2</b>
: This file contains the official FHIR
StructureDefinition files, and the ValueSets needed to support them.
</li>
</ul>
<p>
See the
<a href="./download.html">download page</a>
for more information.
</p>
</subsection>
<subsection name="Running the Validator">
<p>
To execute the validator, you simply create an instance of
<a href="./apidocs-dstu3/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.html">FhirInstanceValidator</a>
and register it to new validator, as shown in the example below.
</p>
<p>
Note that the example below uses the official FHIR StructureDefintions and ValueSets
to validate the resource. It will not work unless you include the
<code>hapi-fhir-validation-resources-[version].jar</code> to your classpath.
</p>
<macro name="snippet">
<param name="id" value="instanceValidator" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
<subsection name="Supplying your own StructureDefinitions">
<p>
The FhirInstanceValidator relies on the
<a href="./apidocs-hl7org-dstu2/ca/uhn/fhir/validation/IValidationSupport.html">IValidationSupport</a>
interface to load StructureDefinitions, and validate codes.
</p>
<p>
By default, the
<a href="./apidocs-hl7org-dstu2/ca/uhn/fhir/validation/DefaultProfileValidationSupport.html">DefaultProfileValidationSupport</a>
implementation is used. This implementation loads the FHIR profiles from the
validator resources JAR. If you want to use your own profiles, you may wish to
supply your own implementation.
</p>
<macro name="snippet">
<param name="id" value="instanceValidatorCustom" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
</section>
</body>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
<properties>
<title>Validation</title>
<author email="jamesagnew@users.sourceforge.net">James Agnew</author>
</properties>
<body>
<section name="Validation">
<p>
HAPI supportes two types of validation, both of which are described in the
sections below.
</p>
<ul>
<li>
<b>Parser Validation</b>
is validation at runtime during the parsing
of a resource. It can be used to catch input data that is impossible to
fit into the HAPI data model. For
example, it can be used to throw exceptions
or display error messages if a resource being parsed contains elements for which
there are no appropriate fields in a HAPI data structure. This is useful in order to ensure
that no data is being lost during parsing, but is less comprehensive than resource validation
against raw text data.
</li>
<li>
<b>Resource Validation</b>
is validation of the raw or parsed resource against
the official FHIR validation rules (e.g. Schema/Schematron/Profile/StructureDefinition/ValueSet)
as well as against custom profiles which have been developed.
</li>
</ul>
</section>
<!-- Parser Validation -->
<section name="Parser Validation">
<p>
Parser validation is controlled by calling
<code>setParserErrorHandler(IParserErrorHandler)</code>
on
either the FhirContext or on individual parser instances. This method
takes an
<code>IParserErrorHandler</code>
, which is a callback that
will be invoked any time a parse issue is detected.
</p>
<p>
There are two implementations of
<code>IParserErrorHandler</code>
worth
mentioning. You can also supply your own implementation if you want.
</p>
<ul>
<li>
<a href="./apidocs/ca/uhn/fhir/parser/LenientErrorHandler.html">LenientErrorHandler</a>
logs any errors but does not abort parsing. By default this handler is used, and it
logs errors at "warning" level. It can also be configured to silently
ignore issues.
</li>
<li>
<a href="./apidocs/ca/uhn/fhir/parser/StrictErrorHandler.html">StrictErrorHandler</a>
throws a
<code>DataFormatException</code>
if any errors are detected.
</li>
</ul>
<p>
The following example shows how to configure a parser to use strict validation.
</p>
<macro name="snippet">
<param name="id" value="parserValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
<p>
You can also configure the error handler at the FhirContext level, which is useful
for clients.
</p>
<macro name="snippet">
<param name="id" value="clientValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
<p>
FhirContext level validators can also be useful on servers.
</p>
<macro name="snippet">
<param name="id" value="serverValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</section>
<!-- RESOURCE VALIDATION -->
<section name="Resource Validation">
<p>
HAPI provides a built-in and configurable mechanism for validating resources.
This mechanism is called the
<i>Resource Validator.</i>
</p>
<p>
The resource validator is an extendible and modular system, and you
can configure it in a number of ways in order to get the specific
type of validation you want to achieve.
</p>
<p>
The validator can be manually invoked at any time by creating a
validator and configuring it with one or more
<a href="./apidocs/ca/uhn/fhir/validation/IValidatorModule.html">IValidatorModule</a>
instances.
</p>
<macro name="snippet">
<param name="id" value="validationIntro" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</section>
<section name="Resource Validation Module: Schema/Schematron">
<p>
FHIR resource definitions are distributed with a set of XML schema files (XSD)
as well as a set of XML Schematron (SCH) files. These two sets of files are
complimentary to each other, meaning that in order to claim compliance to the
FHIR specification, your resources must validate against both sets.
</p>
<p>
The two sets of files are included with HAPI, and it uses them to perform
validation.
</p>
<subsection name="Preparation">
<p>
In order to use HAPI's Schematron support, a libaray called
<a href="https://github.com/phax/ph-schematron">Ph-Schematron</a>
is used, so this library must be added to your classpath (or Maven POM file, Gradle
file, etc.)
Note that this library is specified as an optional dependency
by HAPI FHIR
so you need to explicitly include it if you want to use this
functionality.
</p>
<p>
See
<a href="./download.html">Downloads</a>
for more information on how
to add it.
</p>
</subsection>
<subsection name="Validating a Resource">
<p>
To validate a resource instance, a new validator instance is requested
from the FHIR Context. This validator is then applied against
a specific resource
instance, as shown in the example below.
</p>
<macro name="snippet">
<param name="id" value="basicValidation" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
<subsection name="Validating a Set of Files">
<p>
The following example shows how to load a set of resources from files
on disk and validate each one.
</p>
<macro name="snippet">
<param name="id" value="validateFiles" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
<a name="structure_definition_validation" />
</section>
<section name="Resource Validation (Profile/StructureDefinition)">
<p>
HAPI also supports validation against StructureDefinition
resources. This functionality uses the HL7 "InstanceValidator", which is able
to check a resource for conformance to FHIR profiles
(StructureDefinitions, ValueSets, and CodeSystems),
including validating fields, extensions, and codes for conformance to their given ValueSets.
</p>
<p>
StructureDefinition validation can be used to validate a resource against the
official structure definitions (produced by HL7) as well as against custom
definitions provided either by HL7 or by the user.
</p>
<p class="doc_info_bubble">
The instance validator is experimental in the DSTU2 mode, but has become very stable
and full-featured in DSTU3 mode. Use with caution when validating DSTU2 resources using
instance validator.
</p>
<subsection name="Preparation">
<p>
To use this functionality, you must add the following two dependencies
to your classpath (or Maven POM file, Gradle file, etc.):
</p>
<ul>
<li>
<!-- TODO: add search.maven.org links to these -->
<b>hapi-fhir-structures-hl7org-dstu2</b>
: This file contains the "reference implementation"
structures and tooling. You need to include it even if you are not using the RI model
(the StructureDefinition validation will work against HAPI structures as well)
</li>
<li>
<b>hapi-fhir-validation-resources-dstu2</b>
: This file contains the official FHIR
StructureDefinition files, and the ValueSets needed to support them.
</li>
</ul>
<p>
See the
<a href="./download.html">download page</a>
for more information.
</p>
</subsection>
<subsection name="Running the Validator">
<p>
To execute the validator, you simply create an instance of
<a href="./apidocs-dstu3/org/hl7/fhir/dstu3/hapi/validation/FhirInstanceValidator.html">FhirInstanceValidator</a>
and register it to new validator, as shown in the example below.
</p>
<p>
Note that the example below uses the official FHIR StructureDefintions and ValueSets
to validate the resource. It will not work unless you include the
<code>hapi-fhir-validation-resources-[version].jar</code> to your classpath.
</p>
<macro name="snippet">
<param name="id" value="instanceValidator" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
<subsection name="Supplying your own StructureDefinitions">
<p>
The FhirInstanceValidator relies on the
<a href="./apidocs-hl7org-dstu2/ca/uhn/fhir/validation/IValidationSupport.html">IValidationSupport</a>
interface to load StructureDefinitions, and validate codes.
</p>
<p>
By default, the
<a href="./apidocs-hl7org-dstu2/ca/uhn/fhir/validation/DefaultProfileValidationSupport.html">DefaultProfileValidationSupport</a>
implementation is used. This implementation loads the FHIR profiles from the
validator resources JAR. If you want to use your own profiles, you may wish to
supply your own implementation.
</p>
<macro name="snippet">
<param name="id" value="instanceValidatorCustom" />
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
</macro>
</subsection>
</section>
</body>
</document>

View File

@ -541,13 +541,14 @@ System.setProperty("javax.xml.stream.XMLEventFactory", "com.ctc.wstx.stax.WstxEv
</subsection>
<subsection name="Phloc-Schematron">
<subsection name="Ph-Schematron">
<p>
If you are using the
<a href="./doc_validation.html">Schematron Validatioon</a>
module, you will also need to include the Phloc library on your
classpath.
module, you will also need to include the Ph-Schematron library on your
classpath. (Note that prior to HAPI FHIR 3.4.0 we used Phloc-Schamtron
instead, but that lirary has been discontinued)
</p>
<p>
If you are using Maven, this library is not added by default (it is
@ -556,16 +557,15 @@ System.setProperty("javax.xml.stream.XMLEventFactory", "com.ctc.wstx.stax.WstxEv
dependencies to your project POM.xml
</p>
<source><![CDATA[<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
<version>${phloc_schematron_version}</version>
<groupId>com.helger</groupId>
<artifactId>ph-schematron</artifactId>
<version>${ph_schematron_version}</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<version>${phloc_commons_version}</version>
<groupId>com.helger</groupId>
<artifactId>ph-commons</artifactId>
<version>${ph_commons_version}</version>
</dependency>]]></source>
</subsection>

View File

@ -26,7 +26,7 @@ public class ValidatorTest {
assertEquals("This parser is for FHIR version DSTU2 - Can not encode a structure for version DSTU3", e.getMessage());
}
// Phloc is not onthe classpath
// Ph-Schematron is not onthe classpath
assertTrue(val.isValidateAgainstStandardSchema());
assertFalse(val.isValidateAgainstStandardSchematron());
@ -34,7 +34,7 @@ public class ValidatorTest {
val.setValidateAgainstStandardSchematron(true);
fail();
} catch (IllegalArgumentException e) {
assertEquals("Phloc-schematron library not found on classpath, can not enable perform schematron validation", e.getMessage());
assertEquals("Ph-schematron library not found on classpath, can not enable perform schematron validation", e.getMessage());
}
}