This commit is contained in:
t106uhn 2014-07-02 16:20:20 -04:00
commit 3e8ea1d4ed
236 changed files with 5981 additions and 7330 deletions

View File

@ -10,8 +10,14 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -22,12 +22,13 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>

View File

@ -5,11 +5,21 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
@ -17,7 +27,10 @@
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

View File

@ -1,5 +1,13 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="hapi-fhir-base">
<wb-resource deploy-path="/" source-path="/src/main/java"/>
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
</wb-module>
</project-modules>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.6"/>
</faceted-project>

View File

@ -0,0 +1,2 @@
disabled=06target
eclipse.preferences.version=1

View File

@ -19,7 +19,7 @@
<distributionManagement>
<site>
<id>git.server</id>
<url>scm:git:ssh://git@github.com:jamesagnew/hapi-fhir.git</url>
<url>scm:git:git@github.com:jamesagnew/hapi-fhir.git</url>
</site>
<!-- <site> <id>hl7api.sf.net</id> <url>scp://shell.sourceforge.net/home/project-web/hl7api/htdocs/hapi-fhir</url>
@ -55,7 +55,7 @@
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>2.1.3.RELEASE</version>
<version>${thymeleaf-version}</version>
<optional>true</optional>
</dependency>
@ -101,6 +101,13 @@
<version>4.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring_version}</version>
<optional>true</optional>
</dependency>
<!-- Server -->
<dependency>
<groupId>javax.servlet</groupId>
@ -224,56 +231,19 @@
<escapeHTML>false</escapeHTML>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.16</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
</configuration>
<reportSets>
<reportSet>
<id>default</id>
<reports>
<report>javadoc</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.5.3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>2.4</version>
<reportSets>
<reportSet>
<id>normal</id>
<reports>
<report>jxr</report>
</reports>
</reportSet>
<reportSet>
<id>restful-server-example</id>
<reports>
<report>jxr</report>
</reports>
<configuration>
<sourcePath>../restful-server-example/src/main/java</sourcePath>
<destDir>${project.reporting.outputDirectory}/rse-xref</destDir>
<outputDirectory>tmp</outputDirectory>
<reportOutputDirectory>rse-xref</reportOutputDirectory>
</configuration>
</reportSet>
</reportSets>
</plugin>
<!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-report-plugin</artifactId>
<version>2.16</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <version>2.9.1</version> <configuration>
</configuration> <reportSets> <reportSet> <id>default</id> <reports> <report>javadoc</report>
</reports> </reportSet> </reportSets> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId> <version>2.5.3</version> </plugin>
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jxr-plugin</artifactId>
<version>2.4</version> <reportSets> <reportSet> <id>normal</id> <reports>
<report>jxr</report> </reports> </reportSet> <reportSet> <id>restful-server-example</id>
<reports> <report>jxr</report> </reports> <configuration> <sourcePath>../restful-server-example/src/main/java</sourcePath>
<destDir>${project.reporting.outputDirectory}/rse-xref</destDir> <outputDirectory>tmp</outputDirectory>
<reportOutputDirectory>rse-xref</reportOutputDirectory> </configuration>
</reportSet> </reportSets> </plugin> -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
@ -296,8 +266,10 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<siteMainDirectory>${user.home}/sites/hapi-fhir</siteMainDirectory>
<scmPubCheckoutDirectory>${user.home}/sites/scm/hapi-fhir</scmPubCheckoutDirectory>
</properties>
<build>
<pluginManagement>
<plugins>
@ -305,7 +277,7 @@
<artifactId>maven-site-plugin</artifactId>
<configuration>
<skip>false</skip>
<skipDeploy>false</skipDeploy>
<skipDeploy>true</skipDeploy>
</configuration>
<dependencies>
<dependency>
@ -416,7 +388,9 @@
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-1395874-5', 'sourceforge.net');
ga('create', 'UA-1395874-5', 'auto');
ga('require', 'displayfeatures');
ga('require', 'linkid', 'linkid.js');
ga('send', 'pageview');
</script>
@ -462,6 +436,42 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<executions>
<execution>
<id>stage-for-scm-publish</id>
<phase>post-site</phase>
<goals>
<goal>stage</goal>
</goals>
<configuration>
<stagingDirectory>${siteMainDirectory}</stagingDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-publish-plugin</artifactId>
<version>1.1</version>
<configuration>
<checkoutDirectory>${scmPubCheckoutDirectory}</checkoutDirectory>
<content>\${siteMainDirectory}</content>
<tryUpdate>true</tryUpdate>
<scmBranch>gh-pages</scmBranch>
<pubScmUrl>scm:git:git@github.com:jamesagnew/hapi-fhir.git</pubScmUrl>
</configuration>
<executions>
<execution>
<id>scm-publish</id>
<phase>site-deploy</phase>
<goals>
<goal>publish-scm</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>

View File

@ -56,6 +56,13 @@
<action type="add">
Add support for paging responses from RESTful servers.
</action>
<action type="fix">
Don't fail on narrative blocks in JSON resources with only an XML declaration but no content (these are
produced by the Health Intersections server)
</action>
<action type="fix">
Server now automatically compresses responses if the client indicates support
</action>
</release>
</body>
</document>

View File

@ -66,7 +66,7 @@ public class FhirContext {
private volatile INarrativeGenerator myNarrativeGenerator;
private volatile IRestfulClientFactory myRestfulClientFactory;
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
/**
* Default constructor. In most cases this is the right constructor to use.
*/
@ -77,7 +77,7 @@ public class FhirContext {
public FhirContext(Class<? extends IResource> theResourceType) {
this(toCollection(theResourceType));
}
public FhirContext(Class<?>... theResourceTypes) {
this(toCollection(theResourceTypes));
}
@ -92,10 +92,6 @@ public class FhirContext {
public BaseRuntimeElementDefinition<?> getElementDefinition(Class<? extends IElement> theElementType) {
return myClassToElementDefinition.get(theElementType);
}
public FhirTerser newTerser() {
return new FhirTerser(this);
}
public INarrativeGenerator getNarrativeGenerator() {
return myNarrativeGenerator;
@ -111,7 +107,7 @@ public class FhirContext {
}
return retVal;
}
/**
* Returns the scanned runtime model for the given type. This is an advanced feature which is generally only needed for extending the core library.
*/
@ -226,6 +222,10 @@ public class FhirContext {
return getRestfulClientFactory().newGenericClient(theServerBase);
}
public FhirTerser newTerser() {
return new FhirTerser(this);
}
/**
* Create and return a new JSON parser.
*
@ -241,6 +241,10 @@ public class FhirContext {
myNarrativeGenerator = theNarrativeGenerator;
}
public void setRestfulClientFactory(IRestfulClientFactory theRestfulClientFactory) {
myRestfulClientFactory = theRestfulClientFactory;
}
private RuntimeResourceDefinition scanResourceType(Class<? extends IResource> theResourceType) {
ArrayList<Class<? extends IResource>> resourceTypes = new ArrayList<Class<? extends IResource>>();
resourceTypes.add(theResourceType);
@ -249,7 +253,7 @@ public class FhirContext {
}
private Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> scanResourceTypes(Collection<Class<? extends IResource>> theResourceTypes) {
ModelScanner scanner = new ModelScanner(theResourceTypes);
ModelScanner scanner = new ModelScanner(myClassToElementDefinition, theResourceTypes);
if (myRuntimeChildUndeclaredExtensionDefinition == null) {
myRuntimeChildUndeclaredExtensionDefinition = scanner.getRuntimeChildUndeclaredExtensionDefinition();
}
@ -273,6 +277,11 @@ public class FhirContext {
return classToElementDefinition;
}
/** For unit tests only */
int getElementDefinitionCount() {
return myClassToElementDefinition.size();
}
private static Collection<Class<? extends IResource>> toCollection(Class<? extends IResource> theResourceType) {
ArrayList<Class<? extends IResource>> retVal = new ArrayList<Class<? extends IResource>>(1);
retVal.add(theResourceType);

View File

@ -35,6 +35,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
@ -90,11 +91,15 @@ class ModelScanner {
ModelScanner(Class<? extends IResource> theResourceTypes) throws ConfigurationException {
Set<Class<? extends IElement>> singleton = new HashSet<Class<? extends IElement>>();
singleton.add(theResourceTypes);
init(singleton);
init(null,singleton);
}
ModelScanner(Collection<Class<? extends IResource>> theResourceTypes) throws ConfigurationException {
init(new HashSet<Class<? extends IElement>>(theResourceTypes));
init(null, new HashSet<Class<? extends IElement>>(theResourceTypes));
}
ModelScanner(Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> theExistingDefinitions, Collection<Class<? extends IResource>> theResourceTypes) throws ConfigurationException {
init(theExistingDefinitions, new HashSet<Class<? extends IElement>>(theResourceTypes));
}
public Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> getClassToElementDefinitions() {
@ -147,7 +152,12 @@ class ModelScanner {
}
}
private void init(Set<Class<? extends IElement>> toScan) {
private void init(Map<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> theExistingDefinitions, Set<Class<? extends IElement>> toScan) {
if (theExistingDefinitions!=null) {
myClassToElementDefinitions.putAll(theExistingDefinitions);
}
int startSize = myClassToElementDefinitions.size();
long start = System.currentTimeMillis();
InputStream str = ModelScanner.class.getResourceAsStream("/ca/uhn/fhir/model/dstu/model.properties");
@ -199,7 +209,11 @@ class ModelScanner {
myScanAlso.clear();
} while (!toScan.isEmpty());
for (BaseRuntimeElementDefinition<?> next : myClassToElementDefinitions.values()) {
for (Entry<Class<? extends IElement>, BaseRuntimeElementDefinition<?>> nextEntry : myClassToElementDefinitions.entrySet()) {
if (theExistingDefinitions!=null&&theExistingDefinitions.containsKey(nextEntry.getKey())) {
continue;
}
BaseRuntimeElementDefinition<?> next = nextEntry.getValue();
next.sealAndInitialize(myClassToElementDefinitions);
}
@ -207,7 +221,8 @@ class ModelScanner {
myRuntimeChildUndeclaredExtensionDefinition.sealAndInitialize(myClassToElementDefinitions);
long time = System.currentTimeMillis() - start;
ourLog.info("Done scanning FHIR library, found {} model entries in {}ms", myClassToElementDefinitions.size(), time);
int size = myClassToElementDefinitions.size()- startSize;
ourLog.info("Done scanning FHIR library, found {} model entries in {}ms", size, time);
}
private void scan(Class<? extends IElement> theClass) throws ConfigurationException {

View File

@ -217,14 +217,6 @@ public class Bundle extends BaseBundle /* implements IElement */{
entry.setResource(theResource);
entry.setResource(theResource);
TagList list = (TagList) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (list != null) {
for (Tag tag : list) {
if (StringUtils.isNotBlank(tag.getTerm())) {
entry.addCategory().setTerm(tag.getTerm()).setLabel(tag.getLabel()).setScheme(tag.getScheme());
}
}
}
RuntimeResourceDefinition def = theContext.getResourceDefinition(theResource);

View File

@ -30,7 +30,6 @@ import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
public abstract class ResourceMetadataKeyEnum<T> {
/**
* If present and populated with a date/time (as an instance of {@link InstantDt}),
@ -99,8 +98,7 @@ public abstract class ResourceMetadataKeyEnum<T> {
theResource.getResourceMetadata().put(PUBLISHED, theObject);
}
};
/**
* The value for this key is the list of tags associated with this resource
* <p>
@ -129,7 +127,7 @@ public abstract class ResourceMetadataKeyEnum<T> {
public void put(IResource theResource, TagList theObject) {
theResource.getResourceMetadata().put(TAG_LIST, theObject);
}
};
};
/**
@ -153,7 +151,8 @@ public abstract class ResourceMetadataKeyEnum<T> {
public void put(IResource theResource, InstantDt theObject) {
theResource.getResourceMetadata().put(UPDATED, theObject);
}
};
};
/**
* The value for this key is the version ID of the resource object.
@ -175,22 +174,14 @@ public abstract class ResourceMetadataKeyEnum<T> {
theResource.getResourceMetadata().put(VERSION_ID, theObject);
}
};
private final String myValue;
private final String myValue;
public ResourceMetadataKeyEnum(String theValue) {
myValue = theValue;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((myValue == null) ? 0 : myValue.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
@ -209,50 +200,63 @@ public abstract class ResourceMetadataKeyEnum<T> {
return true;
}
private static IdDt getIdFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum<?>, Object> theResourceMetadata, ResourceMetadataKeyEnum<?> theKey) {
Object retValObj = theResourceMetadata.get(theKey);
if (retValObj == null) {
return null;
} else if (retValObj instanceof String) {
if (isNotBlank((String) retValObj)) {
return new IdDt((String) retValObj);
} else {
return null;
}
} else if (retValObj instanceof IdDt) {
if (((IdDt) retValObj).isEmpty()) {
return null;
} else {
return (IdDt) retValObj;
}
} else if (retValObj instanceof Number) {
return new IdDt(((Number)retValObj).toString());
}
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + IdDt.class.getCanonicalName());
public abstract T get(IResource theResource);
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((myValue == null) ? 0 : myValue.hashCode());
return result;
}
public abstract void put(IResource theResource, T theObject);
@Override
public String toString() {
return myValue;
}
private String name() {
return myValue;
}
private static InstantDt getInstantFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum<?>, Object> theResourceMetadata, ResourceMetadataKeyEnum<InstantDt> theKey) {
Object retValObj = theResourceMetadata.get(theKey);
if (retValObj == null) {
return null;
} else if (retValObj instanceof Date) {
return new InstantDt((Date) retValObj);
} else if (retValObj instanceof InstantDt) {
if (((InstantDt) retValObj).isEmpty()) {
private static IdDt getIdFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum<?>, Object> theResourceMetadata, ResourceMetadataKeyEnum<?> theKey) {
Object retValObj = theResourceMetadata.get(theKey);
if (retValObj == null) {
return null;
} else {
return (InstantDt) retValObj;
} else if (retValObj instanceof String) {
if (isNotBlank((String) retValObj)) {
return new IdDt((String) retValObj);
} else {
return null;
}
} else if (retValObj instanceof IdDt) {
if (((IdDt) retValObj).isEmpty()) {
return null;
} else {
return (IdDt) retValObj;
}
} else if (retValObj instanceof Number) {
return new IdDt(((Number)retValObj).toString());
}
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + IdDt.class.getCanonicalName());
}
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + InstantDt.class.getCanonicalName());
}
public abstract T get(IResource theResource);
public abstract void put(IResource theResource, T theObject);
private static InstantDt getInstantFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum<?>, Object> theResourceMetadata, ResourceMetadataKeyEnum<InstantDt> theKey) {
Object retValObj = theResourceMetadata.get(theKey);
if (retValObj == null) {
return null;
} else if (retValObj instanceof Date) {
return new InstantDt((Date) retValObj);
} else if (retValObj instanceof InstantDt) {
if (((InstantDt) retValObj).isEmpty()) {
return null;
} else {
return (InstantDt) retValObj;
}
}
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + InstantDt.class.getCanonicalName());
}
}

View File

@ -404,8 +404,7 @@ public class IdDt extends BasePrimitive<String> {
* @deprecated Use {@link #getIdPartAsBigDecimal()} instead
*/
public BigDecimal asBigDecimal() {
// TODO Auto-generated method stub
return null;
return getIdPartAsBigDecimal();
}
}

View File

@ -80,6 +80,10 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
if (!val.startsWith("<")) {
val = "<div>" + val + "</div>";
}
if (val.startsWith("<?") && val.endsWith("?>")) {
myValue = null;
return;
}
try {
ArrayList<XMLEvent> value = new ArrayList<XMLEvent>();
@ -99,7 +103,7 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
setValue(value);
} catch (XMLStreamException e) {
throw new DataFormatException("String does not appear to be valid XML/XHTML: "+e.getMessage(), e);
throw new DataFormatException("String does not appear to be valid XML/XHTML (error is \""+e.getMessage() + "\"): " + theValue, e);
} catch (FactoryConfigurationError e) {
throw new ConfigurationException(e);
}

View File

@ -151,6 +151,7 @@ public abstract class BaseClient {
list.add(next.getValue());
}
}
if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() > 299) {
String body=null;

View File

@ -32,6 +32,7 @@ import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.message.BasicHeader;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.util.VersionUtil;
public abstract class BaseHttpClientInvocation {
@ -87,6 +88,11 @@ public abstract class BaseHttpClientInvocation {
theHttpRequest.addHeader(next);
}
}
theHttpRequest.addHeader("User-Agent", "HAPI-FHIR/" + VersionUtil.getVersion() + " (FHIR Client)");
theHttpRequest.addHeader("Accept-Charset", "utf-8");
theHttpRequest.addHeader("Accept-Encoding", "gzip");
}
}

View File

@ -28,7 +28,8 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import ca.uhn.fhir.context.ConfigurationException;
@ -38,9 +39,12 @@ import ca.uhn.fhir.rest.method.BaseMethodBinding;
public class RestfulClientFactory implements IRestfulClientFactory {
private int myConnectionRequestTimeout=10000;
private int myConnectTimeout=10000;
private FhirContext myContext;
private HttpClient myHttpClient;
private Map<Class<? extends IRestfulClient>, ClientInvocationHandler> myInvocationHandlers = new HashMap<Class<? extends IRestfulClient>, ClientInvocationHandler>();
private int mySocketTimeout = 10000;
/**
* Constructor
@ -48,14 +52,63 @@ public class RestfulClientFactory implements IRestfulClientFactory {
* @param theContext
* The context
*/
public RestfulClientFactory(FhirContext theContext) {
public RestfulClientFactory(FhirContext theFhirContext) {
myContext=theFhirContext;
}
/**
* Constructor
*/
public RestfulClientFactory() {
}
/**
* Sets the context associated with this client factory. Must not be called
* more than once.
*/
public void setFhirContext(FhirContext theContext) {
if(myContext!=null&&myContext!=theContext) {
throw new IllegalStateException("RestfulClientFactory instance is already associated with one FhirContext. RestfulClientFactory instances can not be shared.");
}
myContext = theContext;
}
@SuppressWarnings("unchecked")
private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
T proxy = (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
return proxy;
public int getConnectionRequestTimeout() {
return myConnectionRequestTimeout;
}
public int getConnectTimeout() {
return myConnectTimeout;
}
@Override
public synchronized HttpClient getHttpClient() {
if (myHttpClient == null) {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
//@formatter:off
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(mySocketTimeout)
.setConnectTimeout(myConnectTimeout)
.setConnectionRequestTimeout(myConnectionRequestTimeout)
.setStaleConnectionCheckEnabled(true)
.build();
myHttpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(defaultRequestConfig)
.disableCookieManagement()
.build();
//@formatter:on
}
return myHttpClient;
}
public int getSocketTimeout() {
return mySocketTimeout;
}
/**
@ -86,7 +139,7 @@ public class RestfulClientFactory implements IRestfulClientFactory {
if (invocationHandler == null) {
invocationHandler = new ClientInvocationHandler(client, myContext, serverBase, theClientType);
for (Method nextMethod : theClientType.getMethods()) {
BaseMethodBinding binding = BaseMethodBinding.bindMethod(nextMethod, myContext, null);
BaseMethodBinding<?> binding = BaseMethodBinding.bindMethod(nextMethod, myContext, null);
invocationHandler.addBinding(nextMethod, binding);
}
myInvocationHandlers.put(theClientType, invocationHandler);
@ -98,14 +151,18 @@ public class RestfulClientFactory implements IRestfulClientFactory {
}
@Override
public synchronized HttpClient getHttpClient() {
if (myHttpClient == null) {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
myHttpClient = builder.build();
}
return myHttpClient;
public IGenericClient newGenericClient(String theServerBase) {
return new GenericClient(myContext, getHttpClient(), theServerBase);
}
public synchronized void setConnectionRequestTimeout(int theConnectionRequestTimeout) {
myConnectionRequestTimeout = theConnectionRequestTimeout;
myHttpClient=null;
}
public synchronized void setConnectTimeout(int theConnectTimeout) {
myConnectTimeout = theConnectTimeout;
myHttpClient=null;
}
/**
@ -120,9 +177,15 @@ public class RestfulClientFactory implements IRestfulClientFactory {
myHttpClient = theHttpClient;
}
@Override
public IGenericClient newGenericClient(String theServerBase) {
return new GenericClient(myContext, getHttpClient(), theServerBase);
public synchronized void setSocketTimeout(int theSocketTimeout) {
mySocketTimeout = theSocketTimeout;
myHttpClient=null;
}
@SuppressWarnings("unchecked")
private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
T proxy = (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
return proxy;
}
}

View File

@ -177,7 +177,7 @@ public abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding
}
invokeServerMethod(params);
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest);
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
theResponse.setContentType(responseEncoding.getResourceContentType());
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);

View File

@ -30,6 +30,8 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.servlet.http.HttpServletResponse;
@ -60,7 +62,9 @@ import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.param.IParameter;
import ca.uhn.fhir.rest.param.IncludeParameter;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.param.SearchParameter;
import ca.uhn.fhir.rest.server.BundleProviders;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
@ -97,6 +101,16 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
myParameters = ParameterUtil.getResourceParameters(theMethod);
}
public Set<String> getIncludes() {
Set<String> retVal = new TreeSet<String>();
for (IParameter next : myParameters) {
if (next instanceof IncludeParameter) {
retVal.addAll(((IncludeParameter) next).getAllow());
}
}
return retVal;
}
public FhirContext getContext() {
return myContext;
}
@ -114,8 +128,7 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
}
/**
* Returns the name of the resource this method handles, or <code>null</code> if this method is not resource
* specific
* Returns the name of the resource this method handles, or <code>null</code> if this method is not resource specific
*/
public abstract String getResourceName();
@ -251,14 +264,16 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
if (theProvider instanceof IResourceProvider) {
returnTypeFromRp = ((IResourceProvider) theProvider).getResourceType();
if (!verifyIsValidResourceReturnType(returnTypeFromRp)) {
throw new ConfigurationException("getResourceType() from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returned " + toLogString(returnTypeFromRp) + " - Must return a resource type");
throw new ConfigurationException("getResourceType() from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returned "
+ toLogString(returnTypeFromRp) + " - Must return a resource type");
}
}
Class<?> returnTypeFromMethod = theMethod.getReturnType();
if (getTags != null) {
if (!TagList.class.equals(returnTypeFromMethod)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @" + GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
throw new ConfigurationException("Method '" + theMethod.getName() + "' from type " + theMethod.getDeclaringClass().getCanonicalName() + " is annotated with @"
+ GetTags.class.getSimpleName() + " but does not return type " + TagList.class.getName());
}
} else if (MethodOutcome.class.equals(returnTypeFromMethod)) {
// returns a method outcome
@ -271,13 +286,15 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
} else if (Collection.class.isAssignableFrom(returnTypeFromMethod)) {
returnTypeFromMethod = ReflectionUtil.getGenericCollectionTypeOfMethodReturnType(theMethod);
if (!verifyIsValidResourceReturnType(returnTypeFromMethod) && !IResource.class.equals(returnTypeFromMethod)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns a collection with generic type " + toLogString(returnTypeFromMethod)
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
+ " returns a collection with generic type " + toLogString(returnTypeFromMethod)
+ " - Must return a resource type or a collection (List, Set) with a resource type parameter (e.g. List<Patient> )");
}
} else {
if (!IResource.class.equals(returnTypeFromMethod) && !verifyIsValidResourceReturnType(returnTypeFromMethod)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromMethod)
+ " - Must return a resource type (eg Patient, " + Bundle.class.getSimpleName() + ", " + IBundleProvider.class.getSimpleName() + ", etc., see the documentation for more details)");
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName()
+ " returns " + toLogString(returnTypeFromMethod) + " - Must return a resource type (eg Patient, " + Bundle.class.getSimpleName() + ", "
+ IBundleProvider.class.getSimpleName() + ", etc., see the documentation for more details)");
}
}
@ -307,12 +324,13 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
if (returnTypeFromRp != null) {
if (returnTypeFromAnnotation != null && returnTypeFromAnnotation != IResource.class) {
if (!returnTypeFromRp.isAssignableFrom(returnTypeFromAnnotation)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type " + returnTypeFromMethod.getCanonicalName() + " - Must return " + returnTypeFromRp.getCanonicalName()
+ " (or a subclass of it) per IResourceProvider contract");
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " returns type "
+ returnTypeFromMethod.getCanonicalName() + " - Must return " + returnTypeFromRp.getCanonicalName() + " (or a subclass of it) per IResourceProvider contract");
}
if (!returnTypeFromRp.isAssignableFrom(returnTypeFromAnnotation)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " claims to return type " + returnTypeFromAnnotation.getCanonicalName() + " per method annotation - Must return "
+ returnTypeFromRp.getCanonicalName() + " (or a subclass of it) per IResourceProvider contract");
throw new ConfigurationException("Method '" + theMethod.getName() + "' in type " + theMethod.getDeclaringClass().getCanonicalName() + " claims to return type "
+ returnTypeFromAnnotation.getCanonicalName() + " per method annotation - Must return " + returnTypeFromRp.getCanonicalName()
+ " (or a subclass of it) per IResourceProvider contract");
}
returnType = returnTypeFromAnnotation;
} else {
@ -321,8 +339,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
} else {
if (returnTypeFromAnnotation != IResource.class) {
if (!verifyIsValidResourceReturnType(returnTypeFromAnnotation)) {
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type " + theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromAnnotation)
+ " according to annotation - Must return a resource type");
throw new ConfigurationException("Method '" + theMethod.getName() + "' from " + IResourceProvider.class.getSimpleName() + " type "
+ theMethod.getDeclaringClass().getCanonicalName() + " returns " + toLogString(returnTypeFromAnnotation) + " according to annotation - Must return a resource type");
}
returnType = returnTypeFromAnnotation;
} else {
@ -388,8 +406,8 @@ public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T>
if (obj1 == null) {
obj1 = object;
} else {
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @" + obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName()
+ ". Can not have both.");
throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @"
+ obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName() + ". Can not have both.");
}
}

View File

@ -118,8 +118,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
TagList tagList = new TagList();
for (Enumeration<String> enumeration = theRequest.getServletRequest().getHeaders(Constants.HEADER_CATEGORY); enumeration.hasMoreElements();) {
String nextTagComplete = enumeration.nextElement();
StringBuilder next = new StringBuilder(nextTagComplete);
parseTagValue(tagList, nextTagComplete, next);
parseTagValue(tagList, nextTagComplete);
}
if (tagList.isEmpty() == false) {
resource.getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
@ -136,12 +135,12 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
response = (MethodOutcome) invokeServerMethod(params);
} catch (InternalErrorException e) {
ourLog.error("Internal error during method invocation", e);
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
streamOperationOutcome(e, theServer, encoding, theResponse, theRequest);
return;
} catch (BaseServerResponseException e) {
ourLog.info("Exception during method invocation: " + e.getMessage());
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
streamOperationOutcome(e, theServer, encoding, theResponse, theRequest);
return;
}
@ -172,7 +171,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
theServer.addHeadersToResponse(theResponse);
if (response != null && response.getOperationOutcome() != null) {
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
theResponse.setContentType(encoding.getResourceContentType());
Writer writer = theResponse.getWriter();
IParser parser = encoding.newParser(getContext());
@ -191,6 +190,11 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
// getMethod().in
}
static void parseTagValue(TagList tagList, String nextTagComplete) {
StringBuilder next = new StringBuilder(nextTagComplete);
parseTagValue(tagList, nextTagComplete, next);
}
/**
* @throws IOException
*/
@ -256,15 +260,18 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
b.append('/');
b.append(getResourceName());
b.append('/');
b.append(response.getId().getValue());
if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
b.append("/_history/");
b.append(response.getId().getIdPart());
if (response.getId().hasVersionIdPart()) {
b.append("/"+Constants.PARAM_HISTORY+"/");
b.append(response.getId().getVersionIdPart());
}else if (response.getVersionId() != null && response.getVersionId().isEmpty() == false) {
b.append("/"+Constants.PARAM_HISTORY+"/");
b.append(response.getVersionId().getValue());
}
theResponse.addHeader("Location", b.toString());
theResponse.addHeader(Constants.HEADER_LOCATION, b.toString());
}
private void parseTagValue(TagList theTagList, String theCompleteHeaderValue, StringBuilder theBuffer) {
private static void parseTagValue(TagList theTagList, String theCompleteHeaderValue, StringBuilder theBuffer) {
int firstSemicolon = theBuffer.indexOf(";");
int deleteTo;
if (firstSemicolon == -1) {
@ -392,7 +399,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
}
public static MethodOutcome process2xxResponse(FhirContext theContext, String theResourceName, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map<String, List<String>> theHeaders) {
List<String> locationHeaders = theHeaders.get("location");
List<String> locationHeaders = theHeaders.get(Constants.HEADER_LOCATION_LC);
MethodOutcome retVal = new MethodOutcome();
if (locationHeaders != null && locationHeaders.size() > 0) {
String locationHeader = locationHeaders.get(0);

View File

@ -196,7 +196,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
NarrativeModeEnum narrativeMode = RestfulServer.determineNarrativeMode(theRequest);
// Determine response encoding
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest);
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
// Is this request coming from a browser
String uaHeader = theRequest.getServletRequest().getHeader("user-agent");
@ -218,10 +218,12 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
Integer count = RestfulServer.extractCountParameter(theRequest.getServletRequest());
boolean respondGzip=theRequest.isRespondGzip();
IBundleProvider result = invokeServer(theRequest, params);
switch (getReturnType()) {
case BUNDLE:
RestfulServer.streamResponseAsBundle(theServer, theResponse, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, 0, count, null);
RestfulServer.streamResponseAsBundle(theServer, theResponse, result, responseEncoding, theRequest.getFhirServerBase(), theRequest.getCompleteUrl(), prettyPrint, requestIsBrowser, narrativeMode, 0, count, null, respondGzip);
break;
case RESOURCE:
if (result.size() == 0) {
@ -229,69 +231,11 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Obje
} else if (result.size() > 1) {
throw new InternalErrorException("Method returned multiple resources");
}
streamResponseAsResource(theServer, theResponse, result.getResources(0, 1).get(0), responseEncoding, prettyPrint, requestIsBrowser, narrativeMode);
RestfulServer.streamResponseAsResource(theServer, theResponse, result.getResources(0, 1).get(0), responseEncoding, prettyPrint, requestIsBrowser, narrativeMode, respondGzip);
break;
}
}
private void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingEnum theResponseEncoding, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
theHttpResponse.setStatus(200);
if (theResource instanceof Binary) {
Binary bin = (Binary) theResource;
if (isNotBlank(bin.getContentType())) {
theHttpResponse.setContentType(bin.getContentType());
} else {
theHttpResponse.setContentType(Constants.CT_OCTET_STREAM);
}
if (bin.getContent() == null || bin.getContent().length == 0) {
return;
}
theHttpResponse.setContentLength(bin.getContent().length);
ServletOutputStream oos = theHttpResponse.getOutputStream();
oos.write(bin.getContent());
oos.close();
return;
}
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
theHttpResponse.setContentType(theResponseEncoding.getBrowserFriendlyBundleContentType());
} else if (theNarrativeMode == NarrativeModeEnum.ONLY) {
theHttpResponse.setContentType(Constants.CT_HTML);
} else {
theHttpResponse.setContentType(theResponseEncoding.getResourceContentType());
}
theHttpResponse.setCharacterEncoding(Constants.CHARSET_UTF_8);
theServer.addHeadersToResponse(theHttpResponse);
InstantDt lastUpdated = ResourceMetadataKeyEnum.UPDATED.get(theResource);
if (lastUpdated != null) {
theHttpResponse.addHeader(Constants.HEADER_LAST_MODIFIED, lastUpdated.getValueAsString());
}
TagList list = (TagList) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (list != null) {
for (Tag tag : list) {
if (StringUtils.isNotBlank(tag.getTerm())) {
theHttpResponse.addHeader(Constants.HEADER_CATEGORY, tag.toHeaderValue());
}
}
}
PrintWriter writer = theHttpResponse.getWriter();
try {
if (theNarrativeMode == NarrativeModeEnum.ONLY) {
writer.append(theResource.getText().getDiv().getValueAsString());
} else {
RestfulServer.getNewParser(theServer.getFhirContext(), theResponseEncoding, thePrettyPrint, theNarrativeMode).encodeResourceToWriter(theResource, writer);
}
} finally {
writer.close();
}
}
/**
* Subclasses may override

View File

@ -157,7 +157,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
TagList resp = (TagList) invokeServerMethod(params);
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest);
EncodingEnum responseEncoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
theResponse.setContentType(responseEncoding.getResourceContentType());
theResponse.setStatus(Constants.STATUS_HTTP_200_OK);

View File

@ -20,7 +20,6 @@ package ca.uhn.fhir.rest.method;
* #L%
*/
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -48,6 +47,7 @@ public class Request {
private HttpServletResponse myServletResponse;
private IdDt myVersion;
private Map<String,List<String>> myUnqualifiedToQualifiedNames;
private boolean myRespondGzip;
public String getCompleteUrl() {
return myCompleteUrl;
@ -177,4 +177,12 @@ public class Request {
return retVal;
}
public void setRespondGzip(boolean theRespondGzip) {
myRespondGzip=theRespondGzip;
}
public boolean isRespondGzip() {
return myRespondGzip;
}
}

View File

@ -130,7 +130,7 @@ public class TransactionMethodBinding extends BaseResourceReturningMethodBinding
@Override
protected Object parseRequestObject(Request theRequest) throws IOException {
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest);
EncodingEnum encoding = RestfulServer.determineResponseEncoding(theRequest.getServletRequest());
IParser parser = encoding.newParser(getContext());
Bundle bundle = parser.parseBundle(theRequest.getServletRequest().getReader());
return bundle;

View File

@ -73,18 +73,17 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
@Override
protected void addParametersForServerRequest(Request theRequest, Object[] theParams) {
/*
* We are being a bit lenient here, since technically the client is
* supposed to include the version in the Content-Location header, but
* we allow it in the PUT URL as well..
* We are being a bit lenient here, since technically the client is supposed to include the version in the
* Content-Location header, but we allow it in the PUT URL as well..
*/
String locationHeader = theRequest.getServletRequest().getHeader(Constants.HEADER_CONTENT_LOCATION);
IdDt id = new IdDt(locationHeader);
if (isNotBlank(id.getResourceType())) {
if (!getResourceName().equals(id.getResourceType())) {
throw new InvalidRequestException("Attempting to update '"+getResourceName()+ "' but content-location header specifies different resource type '"+id.getResourceType()+"' - header value: " + locationHeader);
throw new InvalidRequestException("Attempting to update '" + getResourceName() + "' but content-location header specifies different resource type '" + id.getResourceType() + "' - header value: " + locationHeader);
}
}
if (isNotBlank(locationHeader)) {
MethodOutcome mo = new MethodOutcome();
parseContentLocation(mo, getResourceName(), locationHeader);
@ -126,15 +125,24 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
}
public static HttpPutClientInvocation createUpdateInvocation(IResource theResource, IdDt idDt, IdDt versionIdDt, FhirContext context) {
String id = idDt.getValue();
String resourceName = context.getResourceDefinition(theResource).getName();
StringBuilder urlExtension = new StringBuilder();
urlExtension.append(resourceName);
urlExtension.append('/');
urlExtension.append(id);
urlExtension.append(idDt.getIdPart());
HttpPutClientInvocation retVal = new HttpPutClientInvocation(context, theResource, urlExtension.toString());
if (versionIdDt != null) {
if (idDt.hasVersionIdPart()) {
String versionId = versionIdDt.getValue();
if (StringUtils.isNotBlank(versionId)) {
StringBuilder b = new StringBuilder();
b.append('/');
b.append(urlExtension);
b.append("/_history/");
b.append(versionId);
retVal.addHeader(Constants.HEADER_CONTENT_LOCATION, b.toString());
}
} else if (versionIdDt != null) {
String versionId = versionIdDt.getValue();
if (StringUtils.isNotBlank(versionId)) {
StringBuilder b = new StringBuilder();
@ -145,7 +153,7 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
retVal.addHeader(Constants.HEADER_CONTENT_LOCATION, b.toString());
}
}
addTagsToPostOrPut(theResource, retVal);
return retVal;
@ -158,7 +166,7 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
if (theRequest.getVersionId() == null) {
return false;
}
}else {
} else {
if (theRequest.getVersionId() != null) {
return false;
}

View File

@ -22,8 +22,10 @@ package ca.uhn.fhir.rest.param;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import ca.uhn.fhir.context.ConfigurationException;
@ -38,8 +40,8 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class IncludeParameter extends BaseQueryParameter {
private Set<String> myAllow;
private Class<? extends Collection<Include>> myInstantiableCollectionType;
private HashSet<String> myAllow;
private Class<?> mySpecType;
public IncludeParameter(IncludeParam theAnnotation, Class<? extends Collection<Include>> theInstantiableCollectionType, Class<?> theSpecType) {
@ -47,8 +49,12 @@ public class IncludeParameter extends BaseQueryParameter {
if (theAnnotation.allow().length > 0) {
myAllow = new HashSet<String>();
for (String next : theAnnotation.allow()) {
myAllow.add(next);
if (next != null) {
myAllow.add(next);
}
}
} else {
myAllow = Collections.emptySet();
}
mySpecType = theSpecType;
@ -66,7 +72,7 @@ public class IncludeParameter extends BaseQueryParameter {
if (myInstantiableCollectionType == null) {
if (mySpecType == Include.class) {
retVal.add(QualifiedParamList.singleton(((Include) theObject).getValue()));
}else if (mySpecType == PathSpecification.class) {
} else if (mySpecType == PathSpecification.class) {
retVal.add(QualifiedParamList.singleton(((PathSpecification) theObject).getValue()));
} else {
retVal.add(QualifiedParamList.singleton(((String) theObject)));
@ -81,11 +87,30 @@ public class IncludeParameter extends BaseQueryParameter {
return retVal;
}
public Set<String> getAllow() {
return myAllow;
}
@Override
public String getName() {
return "_include";
}
@Override
public SearchParamTypeEnum getParamType() {
return null;
}
@Override
public boolean handlesMissing() {
return true;
}
@Override
public boolean isRequired() {
return false;
}
@Override
public Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
Collection<Include> retValCollection = null;
@ -131,19 +156,4 @@ public class IncludeParameter extends BaseQueryParameter {
return retValCollection;
}
@Override
public boolean isRequired() {
return false;
}
@Override
public SearchParamTypeEnum getParamType() {
return null;
}
@Override
public boolean handlesMissing() {
return true;
}
}

View File

@ -45,6 +45,7 @@ public class Constants {
public static final String HEADER_ACCEPT = "Accept";
public static final String HEADER_CATEGORY = "Category";
public static final String HEADER_CONTENT_LOCATION = "Content-Location";
public static final String HEADER_CONTENT_LOCATION_LC = HEADER_CONTENT_LOCATION.toLowerCase();
public static final String HEADER_CONTENT_TYPE = "Content-Type";
public static final String HEADER_LAST_MODIFIED = "Last-Modified";
public static final String HEADER_LAST_MODIFIED_LOWERCASE = HEADER_LAST_MODIFIED.toLowerCase();
@ -81,6 +82,11 @@ public class Constants {
public static final int STATUS_HTTP_422_UNPROCESSABLE_ENTITY = 422;
public static final int STATUS_HTTP_500_INTERNAL_ERROR = 500;
public static final String URL_TOKEN_HISTORY = "_history";
public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
public static final String ENCODING_GZIP = "gzip";
public static final String HEADER_LOCATION = "Location";
public static final String HEADER_LOCATION_LC = HEADER_LOCATION.toLowerCase();
static {

View File

@ -46,6 +46,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
registerExceptionType(ResourceVersionNotSpecifiedException.STATUS_CODE, ResourceVersionNotSpecifiedException.class);
registerExceptionType(ResourceVersionConflictException.STATUS_CODE, ResourceVersionConflictException.class);
registerExceptionType(UnprocessableEntityException.STATUS_CODE, UnprocessableEntityException.class);
registerExceptionType(ResourceGoneException.STATUS_CODE, ResourceGoneException.class);
}
private final OperationOutcome myOperationOutcome;

View File

@ -0,0 +1,54 @@
package ca.uhn.fhir.rest.server.exceptions;
/*
* #%L
* HAPI FHIR Library
* %%
* Copyright (C) 2014 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.Constants;
/**
* Represents an <b>HTTP 410 Resource Gone</b> response, which gvenerally
* indicates that the resource has been deleted
*/
public class ResourceGoneException extends BaseServerResponseException {
public static final int STATUS_CODE = Constants.STATUS_HTTP_410_GONE;
public ResourceGoneException(IdDt theId) {
super(STATUS_CODE, "Resource " + (theId != null ? theId.getValue() : "") + " is gone/deleted");
}
public ResourceGoneException(Class<? extends IResource> theClass, IdentifierDt thePatientId) {
super(STATUS_CODE, "Resource of type " + theClass.getSimpleName() + " with ID " + thePatientId + " is gone/deleted");
}
public ResourceGoneException(Class<? extends IResource> theClass, IdDt thePatientId) {
super(STATUS_CODE, "Resource of type " + theClass.getSimpleName() + " with ID " + thePatientId + " is gone/deleted");
}
public ResourceGoneException(String theMessage) {
super(STATUS_CODE, theMessage);
}
private static final long serialVersionUID = 1L;
}

View File

@ -28,8 +28,12 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
@ -70,6 +74,8 @@ public class ServerConformanceProvider {
}
Conformance retVal = new Conformance();
retVal.getImplementation().setDescription(myRestfulServer.getImplementationDescription());
retVal.getSoftware().setName(myRestfulServer.getServerName());
retVal.getSoftware().setVersion(myRestfulServer.getServerVersion());
retVal.addFormat(Constants.CT_FHIR_XML);
@ -98,6 +104,8 @@ public class ServerConformanceProvider {
resource.getType().setValue(def.getName());
resource.getProfile().setId(new IdDt(def.getResourceProfile()));
TreeSet<String> includes = new TreeSet<String>();
Map<String, Conformance.RestResourceSearchParam> nameToSearchParam = new HashMap<String, Conformance.RestResourceSearchParam>();
for (BaseMethodBinding<?> nextMethodBinding : next.getMethodBindings()) {
RestfulOperationTypeEnum resOp = nextMethodBinding.getResourceOperationType();
@ -117,7 +125,10 @@ public class ServerConformanceProvider {
}
if (nextMethodBinding instanceof SearchMethodBinding) {
List<IParameter> params = ((SearchMethodBinding) nextMethodBinding).getParameters();
SearchMethodBinding searchMethodBinding = (SearchMethodBinding) nextMethodBinding;
includes.addAll(searchMethodBinding.getIncludes());
List<IParameter> params = searchMethodBinding.getParameters();
List<SearchParameter> searchParameters = new ArrayList<SearchParameter>();
for (IParameter nextParameter : params) {
if ((nextParameter instanceof SearchParameter)) {
@ -128,12 +139,12 @@ public class ServerConformanceProvider {
@Override
public int compare(SearchParameter theO1, SearchParameter theO2) {
if (theO1.isRequired() == theO2.isRequired()) {
return 0;
return theO1.getName().compareTo(theO2.getName());
}
if (theO1.isRequired()) {
return 1;
return -1;
}
return -1;
return 1;
}
});
if (searchParameters.isEmpty()) {
@ -145,11 +156,33 @@ public class ServerConformanceProvider {
ExtensionDt searchParamChain = null;
for (SearchParameter nextParameter : searchParameters) {
String nextParamName = nextParameter.getName();
String chain = null;
if (nextParamName.contains(".")) {
chain = nextParamName.substring(nextParamName.indexOf('.') + 1);
nextParamName = nextParamName.substring(0, nextParamName.indexOf('.'));
}
String nextParamDescription = nextParameter.getDescription();
/*
* If the parameter has no description, default to the one from the resource
*/
if (StringUtils.isBlank(nextParamDescription)) {
RuntimeSearchParam paramDef = def.getSearchParam(nextParamName);
if (paramDef != null) {
nextParamDescription = paramDef.getDescription();
}
}
if (searchParam == null || allOptional) {
if (!nameToSearchParam.containsKey(nextParameter.getName())) {
RestResourceSearchParam param = resource.addSearchParam();
param.setName(nextParameter.getName());
param.setDocumentation(nextParameter.getDescription());
param.setName(nextParamName);
if (StringUtils.isNotBlank(chain)) {
param.addChain(chain);
}
param.setDocumentation(nextParamDescription);
param.setType(nextParameter.getParamType());
searchParam = param;
} else {
@ -162,22 +195,20 @@ public class ServerConformanceProvider {
} else {
searchParamChain = searchParam.addUndeclaredExtension(false, ExtensionConstants.CONF_ADDITIONAL_PARAM);
// if (searchParamChain == null) {
// } else {
// searchParamChain = searchParamChain.addUndeclaredExtension(false,
// ExtensionConstants.CONF_ADDITIONAL_PARAM);
// }
if (searchParamChain == null) {
searchParamChain = searchParam.addUndeclaredExtension(false, ExtensionConstants.CONF_ADDITIONAL_PARAM);
} else {
searchParamChain = searchParamChain.addUndeclaredExtension(false, ExtensionConstants.CONF_ADDITIONAL_PARAM);
}
ExtensionDt ext = new ExtensionDt();
ext.setUrl(ExtensionConstants.CONF_ADDITIONAL_PARAM_NAME);
ext.setValue(new StringDt(nextParameter.getName()));
ext.setValue(new StringDt(nextParamName));
searchParamChain.getUndeclaredExtensions().add(ext);
ext = new ExtensionDt();
ext.setUrl(ExtensionConstants.CONF_ADDITIONAL_PARAM_DESCRIPTION);
ext.setValue(new StringDt(nextParameter.getDescription()));
ext.setValue(new StringDt(nextParamDescription));
searchParamChain.getUndeclaredExtensions().add(ext);
ext = new ExtensionDt();
@ -217,6 +248,10 @@ public class ServerConformanceProvider {
}
for (String nextInclude : includes) {
resource.addSearchInclude(nextInclude);
}
}
myConformance = retVal;
@ -224,8 +259,7 @@ public class ServerConformanceProvider {
}
/**
* Sets the cache property (default is true). If set to true, the same response will be returned for each
* invocation.
* Sets the cache property (default is true). If set to true, the same response will be returned for each invocation.
*/
public void setCache(boolean theCache) {
myCache = theCache;

View File

@ -1,508 +0,0 @@
package ca.uhn.fhir.rest.server.tester;
/*
* #%L
* HAPI FHIR Library
* %%
* Copyright (C) 2014 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.WriterOutputStream;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.resourceresolver.IResourceResolver;
import org.thymeleaf.standard.StandardDialect;
import org.thymeleaf.templateresolver.TemplateResolver;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.annotation.Metadata;
import ca.uhn.fhir.rest.client.GenericClient;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
public class RestfulServerTesterServlet extends HttpServlet {
private static final boolean DEBUGMODE = true;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerTesterServlet.class);
private static final String PUBLIC_TESTER_RESULT_HTML = "/PublicTesterResult.html";
private static final long serialVersionUID = 1L;
private FhirContext myCtx;
private String myServerBase;
private HashMap<String, String> myStaticResources;
private TemplateEngine myTemplateEngine;
private Set<String> myFilterHeaders;
public RestfulServerTesterServlet() {
myStaticResources = new HashMap<String, String>();
myStaticResources.put("jquery-2.1.0.min.js", "text/javascript");
myStaticResources.put("PublicTester.js", "text/javascript");
myStaticResources.put("PublicTester.css", "text/css");
myStaticResources.put("hapi_fhir_banner.png", "image/png");
myStaticResources.put("hapi_fhir_banner_right.png", "image/png");
myStaticResources.put("shCore.js", "text/javascript");
myStaticResources.put("shBrushJScript.js", "text/javascript");
myStaticResources.put("shBrushXml.js", "text/javascript");
myStaticResources.put("shBrushPlain.js", "text/javascript");
myStaticResources.put("shCore.css", "text/css");
myStaticResources.put("shThemeDefault.css", "text/css");
myStaticResources.put("json2.js", "text/javascript");
myStaticResources.put("minify.json.js", "text/javascript");
myCtx = new FhirContext();
}
public FhirContext getFhirContext() {
return myCtx;
}
@Override
public void init(ServletConfig theConfig) throws ServletException {
myTemplateEngine = new TemplateEngine();
TemplateResolver resolver = new TemplateResolver();
resolver.setResourceResolver(new ProfileResourceResolver());
myTemplateEngine.setTemplateResolver(resolver);
StandardDialect dialect = new StandardDialect();
myTemplateEngine.setDialect(dialect);
myTemplateEngine.initialize();
}
public void setServerBase(String theServerBase) {
myServerBase = theServerBase;
}
private RuntimeResourceDefinition getResourceType(HttpServletRequest theReq) throws ServletException {
String resourceName = StringUtils.defaultString(theReq.getParameter("resourceName"));
RuntimeResourceDefinition def = myCtx.getResourceDefinition(resourceName);
if (def == null) {
throw new ServletException("Invalid resourceName: " + resourceName);
}
return def;
}
private void streamResponse(String theResourceName, String theContentType, HttpServletResponse theResp) throws IOException {
InputStream res = RestfulServerTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/" + theResourceName);
theResp.setContentType(theContentType);
IOUtils.copy(res, theResp.getOutputStream());
}
@Override
protected void doGet(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
if (DEBUGMODE) {
myTemplateEngine.getCacheManager().clearAllCaches();
}
try {
ourLog.info("RequestURI: {}", theReq.getPathInfo());
String resName = theReq.getPathInfo().substring(1);
if (myStaticResources.containsKey(resName)) {
streamResponse(resName, myStaticResources.get(resName), theResp);
return;
}
ConformanceClient client = myCtx.newRestfulClient(ConformanceClient.class, myServerBase);
Conformance conformance = client.getConformance();
WebContext ctx = new WebContext(theReq, theResp, theReq.getServletContext(), theReq.getLocale());
ctx.setVariable("conf", conformance);
ctx.setVariable("base", myServerBase);
ctx.setVariable("jsonEncodedConf", myCtx.newJsonParser().encodeResourceToString(conformance));
addStandardVariables(ctx, theReq.getParameterMap());
theResp.setContentType("text/html");
theResp.setCharacterEncoding("UTF-8");
myTemplateEngine.process(theReq.getPathInfo(), ctx, theResp.getWriter());
} catch (Exception e) {
ourLog.error("Failed to respond", e);
theResp.sendError(500, e.getMessage());
}
}
private void addStandardVariables(WebContext theCtx, Map<String, String[]> theParameterMap) {
addStandardVariable(theCtx, theParameterMap, "configEncoding");
addStandardVariable(theCtx, theParameterMap, "configPretty");
}
private void addStandardVariable(WebContext theCtx, Map<String, String[]> theParameterMap, String key) {
if (theParameterMap.containsKey(key) && theParameterMap.get(key).length > 0) {
theCtx.setVariable(key, theParameterMap.get(key)[0]);
}
}
@Override
protected void doPost(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
if (DEBUGMODE) {
myTemplateEngine.getCacheManager().clearAllCaches();
}
GenericClient client = (GenericClient) myCtx.newRestfulGenericClient(myServerBase);
client.setKeepResponses(true);
boolean returnsResource;
long latency=0;
try {
String method = theReq.getParameter("method");
String prettyParam = theReq.getParameter("configPretty");
if ("on".equals(prettyParam)) {
client.setPrettyPrint(true);
}
if ("xml".equals(theReq.getParameter("configEncoding"))) {
client.setEncoding(EncodingEnum.XML);
} else if ("json".equals(theReq.getParameter("configEncoding"))) {
client.setEncoding(EncodingEnum.JSON);
}
long start = System.currentTimeMillis();
if ("conformance".equals(method)) {
returnsResource = true;
client.conformance();
} else if ("read".equals(method)) {
RuntimeResourceDefinition def = getResourceType(theReq);
String id = StringUtils.defaultString(theReq.getParameter("id"));
if (StringUtils.isBlank(id)) {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "No ID specified");
}
returnsResource = true;
client.read(def.getImplementingClass(), new IdDt(id));
} else if ("vread".equals(method)) {
RuntimeResourceDefinition def = getResourceType(theReq);
String id = StringUtils.defaultString(theReq.getParameter("id"));
if (StringUtils.isBlank(id)) {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "No ID specified");
}
String versionId = StringUtils.defaultString(theReq.getParameter("versionid"));
if (StringUtils.isBlank(versionId)) {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "No Version ID specified");
}
returnsResource = true;
client.vread(def.getImplementingClass(), new IdDt(id), new IdDt(versionId));
} else if ("delete".equals(method)) {
RuntimeResourceDefinition def = getResourceType(theReq);
String id = StringUtils.defaultString(theReq.getParameter("id"));
if (StringUtils.isBlank(id)) {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "No ID specified");
}
returnsResource = false;
client.delete(def.getImplementingClass(), new IdDt(id));
} else if ("history-instance".equals(method) || "history-server".equals(method) || "history-type".equals(method)) {
RuntimeResourceDefinition def = getResourceType(theReq);
String id = StringUtils.defaultString(theReq.getParameter("id"));
if (StringUtils.isBlank(id)) {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "No ID specified");
}
returnsResource = false;
client.history(def.getImplementingClass(), new IdDt(id),null,null);
} else if ("create".equals(method)) {
IResource resource = parseIncomingResource(theReq, theResp, client);
returnsResource = false;
client.create(resource);
} else if ("validate".equals(method)) {
IResource resource = parseIncomingResource(theReq, theResp, client);
returnsResource = false;
client.validate(resource);
} else if ("update".equals(method)) {
String id = StringUtils.defaultString(theReq.getParameter("id"));
if (StringUtils.isBlank(id)) {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "No ID specified");
}
IResource resource = parseIncomingResource(theReq, theResp, client);
returnsResource = false;
client.update(new IdDt(id), resource);
} else if ("searchType".equals(method)) {
Map<String, List<IQueryParameterType>> params = new HashMap<String, List<IQueryParameterType>>();
HashSet<String> hashSet = new HashSet<String>(theReq.getParameterMap().keySet());
String paramName = null;
IQueryParameterType paramValue = null;
while (hashSet.isEmpty() == false) {
String nextKey = hashSet.iterator().next();
String nextValue = theReq.getParameter(nextKey);
paramName = null;
paramValue = null;
if (nextKey.startsWith("param.token.")) {
int prefixLength = "param.token.".length();
paramName = nextKey.substring(prefixLength + 2);
String systemKey = "param.token." + "1." + paramName;
String valueKey = "param.token." + "2." + paramName;
String system = theReq.getParameter(systemKey);
String value = theReq.getParameter(valueKey);
paramValue = new IdentifierDt(system, value);
hashSet.remove(systemKey);
hashSet.remove(valueKey);
} else if (nextKey.startsWith("param.string.")) {
paramName = nextKey.substring("param.string.".length());
paramValue = new StringDt(nextValue);
}
if (paramName != null) {
if (params.containsKey(paramName) == false) {
params.put(paramName, new ArrayList<IQueryParameterType>());
}
params.get(paramName).add(paramValue);
}
hashSet.remove(nextKey);
}
RuntimeResourceDefinition def = getResourceType(theReq);
returnsResource = false;
client.search(def.getImplementingClass(), params);
} else {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "Invalid method: " + method);
return;
}
latency = System.currentTimeMillis() - start;
} catch (DataFormatException e) {
ourLog.error("Failed to invoke method", e);
returnsResource = false;
} catch (Exception e) {
ourLog.error("Failure during processing", e);
returnsResource = false;
}
try {
HttpRequestBase lastRequest = client.getLastRequest();
String requestBody = null;
String requestSyntaxHighlighterClass = null;
if (lastRequest instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest lastEERequest = (HttpEntityEnclosingRequest) lastRequest;
HttpEntity lastEE = lastEERequest.getEntity();
if (lastEE.isRepeatable()) {
StringWriter requestCapture = new StringWriter();
lastEE.writeTo(new WriterOutputStream(requestCapture, "UTF-8"));
requestBody = requestCapture.toString();
ContentType ct = ContentType.get(lastEE);
String mimeType = ct.getMimeType();
EncodingEnum ctEnum = EncodingEnum.forContentType(mimeType);
if (ctEnum == null) {
requestSyntaxHighlighterClass = "brush: plain";
} else {
switch (ctEnum) {
case JSON:
requestSyntaxHighlighterClass = "brush: jscript";
break;
case XML:
default:
requestSyntaxHighlighterClass = "brush: xml";
break;
}
}
}
}
String resultSyntaxHighlighterClass;
String requestUrl = lastRequest != null ? lastRequest.getURI().toASCIIString() : null;
String action = client.getLastRequest() != null ? client.getLastRequest().getMethod() : null;
String resultStatus = client.getLastResponse() != null ? client.getLastResponse().getStatusLine().toString() : null;
String resultBody = client.getLastResponseBody();
HttpResponse lastResponse = client.getLastResponse();
ContentType ct = lastResponse != null ? ContentType.get(lastResponse.getEntity()) : null;
String mimeType = ct != null ? ct.getMimeType() : null;
EncodingEnum ctEnum = EncodingEnum.forContentType(mimeType);
String narrativeString = "";
if (ctEnum == null) {
resultSyntaxHighlighterClass = "brush: plain";
} else {
switch (ctEnum) {
case JSON:
resultSyntaxHighlighterClass = "brush: jscript";
if (returnsResource) {
narrativeString = parseNarrative(ctEnum, resultBody);
}
break;
case XML:
default:
resultSyntaxHighlighterClass = "brush: xml";
if (returnsResource) {
narrativeString = parseNarrative(ctEnum, resultBody);
}
break;
}
}
Header[] requestHeaders = lastRequest != null ? applyHeaderFilters(lastRequest.getAllHeaders()) : new Header[0];
Header[] responseHeaders = lastResponse != null ? applyHeaderFilters(lastResponse.getAllHeaders()) : new Header[0];
WebContext ctx = new WebContext(theReq, theResp, theReq.getServletContext(), theReq.getLocale());
ctx.setVariable("base", myServerBase);
ctx.setVariable("requestUrl", requestUrl);
ctx.setVariable("action", action);
ctx.setVariable("resultStatus", resultStatus);
ctx.setVariable("requestBody", StringEscapeUtils.escapeHtml4(requestBody));
ctx.setVariable("requestSyntaxHighlighterClass", requestSyntaxHighlighterClass);
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml4(resultBody));
ctx.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
ctx.setVariable("requestHeaders", requestHeaders);
ctx.setVariable("responseHeaders", responseHeaders);
ctx.setVariable("narrative", narrativeString);
ctx.setVariable("latencyMs", latency);
myTemplateEngine.process(PUBLIC_TESTER_RESULT_HTML, ctx, theResp.getWriter());
} catch (Exception e) {
ourLog.error("Failure during processing", e);
theResp.sendError(500, e.toString());
}
}
private IResource parseIncomingResource(HttpServletRequest theReq, HttpServletResponse theResp, GenericClient theClient) throws ServletException, IOException {
RuntimeResourceDefinition def = getResourceType(theReq);
String resourceText = StringUtils.defaultString(theReq.getParameter("resource"));
if (StringUtils.isBlank(resourceText)) {
theResp.sendError(Constants.STATUS_HTTP_400_BAD_REQUEST, "No resource content specified");
}
IResource resource;
if (theClient.getEncoding() == null) {
if (resourceText.trim().startsWith("{")) {
resource = myCtx.newJsonParser().parseResource(def.getImplementingClass(), resourceText);
} else {
resource = myCtx.newXmlParser().parseResource(def.getImplementingClass(), resourceText);
}
} else if (theClient.getEncoding() == EncodingEnum.XML) {
resource = myCtx.newXmlParser().parseResource(def.getImplementingClass(), resourceText);
} else {
resource = myCtx.newJsonParser().parseResource(def.getImplementingClass(), resourceText);
}
return resource;
}
private Header[] applyHeaderFilters(Header[] theAllHeaders) {
if (myFilterHeaders == null || myFilterHeaders.isEmpty()) {
return theAllHeaders;
}
ArrayList<Header> retVal = new ArrayList<Header>();
for (Header next : theAllHeaders) {
if (!myFilterHeaders.contains(next.getName().toLowerCase())) {
retVal.add(next);
}
}
return retVal.toArray(new Header[retVal.size()]);
}
/**
* If set, the headers named here will be stripped from requests/responses before they are displayed to the user.
* This can be used, for instance, to filter out "Authorization" headers. Note that names are not case sensitive.
*/
public void setFilterHeaders(String... theHeaderNames) {
myFilterHeaders = new HashSet<String>();
if (theHeaderNames != null) {
for (String next : theHeaderNames) {
myFilterHeaders.add(next.toLowerCase());
}
}
}
private String parseNarrative(EncodingEnum theCtEnum, String theResultBody) {
try {
IResource resource = theCtEnum.newParser(myCtx).parseResource(theResultBody);
String retVal = resource.getText().getDiv().getValueAsString();
return StringUtils.defaultString(retVal);
} catch (Exception e) {
ourLog.error("Failed to parse resource", e);
return "";
}
}
private interface ConformanceClient extends IBasicClient {
@Metadata
Conformance getConformance();
}
private final class ProfileResourceResolver implements IResourceResolver {
@Override
public String getName() {
return getClass().getCanonicalName();
}
@Override
public InputStream getResourceAsStream(TemplateProcessingParameters theTemplateProcessingParameters, String theName) {
ourLog.debug("Loading template: {}", theName);
if ("/".equals(theName)) {
return RestfulServerTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/PublicTester.html");
}
if (PUBLIC_TESTER_RESULT_HTML.equals(theName)) {
return RestfulServerTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/PublicTesterResult.html");
}
return null;
}
}
}

View File

@ -1,880 +0,0 @@
package ca.uhn.fhir.rest.server.tester;
/*
* #%L
* HAPI FHIR Library
* %%
* Copyright (C) 2014 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.WriterOutputStream;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.TemplateProcessingParameters;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.resourceresolver.IResourceResolver;
import org.thymeleaf.standard.StandardDialect;
import org.thymeleaf.templateresolver.TemplateResolver;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Conformance.Rest;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.annotation.Metadata;
import ca.uhn.fhir.rest.client.GenericClient;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.gclient.IQuery;
import ca.uhn.fhir.rest.gclient.IUntypedQuery;
import ca.uhn.fhir.rest.gclient.StringParam;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
public class RestfulTesterServlet extends HttpServlet {
private static final String PARAM_RESOURCE = "resource";
private static final String RESOURCE_COUNT_EXT_URL = "http://hl7api.sourceforge.net/hapi-fhir/res/extdefs.html#resourceCount";
private static final boolean DEBUGMODE = true;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulTesterServlet.class);
private static final String PUBLIC_TESTER_RESULT_HTML = "/PublicTesterResult.html";
private static final long serialVersionUID = 1L;
private FhirContext myCtx;
private String myServerBase;
private HashMap<String, String> myStaticResources;
private TemplateEngine myTemplateEngine;
private Set<String> myFilterHeaders;
public RestfulTesterServlet() {
myStaticResources = new HashMap<String, String>();
myStaticResources.put("jquery-2.1.0.min.js", "text/javascript");
myStaticResources.put("PublicTester.js", "text/javascript");
myStaticResources.put("PublicTester.css", "text/css");
myStaticResources.put("hapi_fhir_banner.png", "image/png");
myStaticResources.put("hapi_fhir_banner_right.png", "image/png");
myStaticResources.put("shCore.js", "text/javascript");
myStaticResources.put("shBrushJScript.js", "text/javascript");
myStaticResources.put("shBrushXml.js", "text/javascript");
myStaticResources.put("shBrushPlain.js", "text/javascript");
myStaticResources.put("shCore.css", "text/css");
myStaticResources.put("shThemeDefault.css", "text/css");
myStaticResources.put("json2.js", "text/javascript");
myStaticResources.put("minify.json.js", "text/javascript");
myStaticResources.put("css/bootstrap.min.css", "text/css");
myStaticResources.put("css/tester.css", "text/css");
myStaticResources.put("img/hapi_fhir_banner.png", "image/png");
myStaticResources.put("img/hapi_fhir_banner_right.png", "image/png");
myStaticResources.put("js/bootstrap.min.js", "text/javascript");
myStaticResources.put("js/jquery-2.1.0.min.js", "text/javascript");
myStaticResources.put("css/bootstrap-datetimepicker.min.css", "text/css");
myStaticResources.put("js/bootstrap-datetimepicker.min.js", "text/javascript");
myStaticResources.put("js/moment.min.js", "text/javascript");
myStaticResources.put("js/select2.min.js", "text/javascript");
myStaticResources.put("css/select2.css", "text/css");
myStaticResources.put("css/select2.png", "image/png");
myStaticResources.put("css/select2x2.png", "image/png");
myStaticResources.put("css/select2-spinner.gif", "image/gif");
myStaticResources.put("fonts/glyphicons-halflings-regular.eot", "application/octet-stream");
myStaticResources.put("fonts/glyphicons-halflings-regular.svg", "application/octet-stream");
myStaticResources.put("fonts/glyphicons-halflings-regular.ttf", "application/octet-stream");
myStaticResources.put("fonts/glyphicons-halflings-regular.woff", "application/octet-stream");
myStaticResources.put("fa/css/font-awesome.css", "text/css");
myStaticResources.put("fa/css/font-awesome.min.css", "text/css");
myStaticResources.put("fa/fonts/fontawesome-webfont.eot", "application/octet-stream");
myStaticResources.put("fa/fonts/fontawesome-webfont.svg", "application/octet-stream");
myStaticResources.put("fa/fonts/fontawesome-webfont.ttf", "application/octet-stream");
myStaticResources.put("fa/fonts/fontawesome-webfont.woff", "application/octet-stream");
myStaticResources.put("fa/fonts/FontAwesome.otf", "application/octet-stream");
myStaticResources.put("fa/less/bordered-pulled.less", "text/css");
myStaticResources.put("fa/less/core.less", "text/css");
myStaticResources.put("fa/less/fixed-width.less", "text/css");
myStaticResources.put("fa/less/font-awesome.less", "text/css");
myStaticResources.put("fa/less/icons.less", "text/css");
myStaticResources.put("fa/less/larger.less", "text/css");
myStaticResources.put("fa/less/list.less", "text/css");
myStaticResources.put("fa/less/mixins.less", "text/css");
myStaticResources.put("fa/less/path.less", "text/css");
myStaticResources.put("fa/less/rotated-flipped.less", "text/css");
myStaticResources.put("fa/less/spinning.less", "text/css");
myStaticResources.put("fa/less/stacked.less", "text/css");
myStaticResources.put("fa/less/variables.less", "text/css");
myStaticResources.put("fa/scss/_bordered-pulled.scss", "text/css");
myStaticResources.put("fa/scss/_core.scss", "text/css");
myStaticResources.put("fa/scss/_fixed-width.scss", "text/css");
myStaticResources.put("fa/scss/_icons.scss", "text/css");
myStaticResources.put("fa/scss/_larger.scss", "text/css");
myStaticResources.put("fa/scss/_list.scss", "text/css");
myStaticResources.put("fa/scss/_mixins.scss", "text/css");
myStaticResources.put("fa/scss/_path.scss", "text/css");
myStaticResources.put("fa/scss/_rotated-flipped.scss", "text/css");
myStaticResources.put("fa/scss/_spinning.scss", "text/css");
myStaticResources.put("fa/scss/_stacked.scss", "text/css");
myStaticResources.put("fa/scss/_variables.scss", "text/css");
myStaticResources.put("fa/scss/font-awesome.scss", "text/css");
myCtx = new FhirContext();
}
public FhirContext getFhirContext() {
return myCtx;
}
@Override
public void init(ServletConfig theConfig) throws ServletException {
myTemplateEngine = new TemplateEngine();
TemplateResolver resolver = new TemplateResolver();
resolver.setResourceResolver(new ProfileResourceResolver());
myTemplateEngine.setTemplateResolver(resolver);
StandardDialect dialect = new StandardDialect();
myTemplateEngine.setDialect(dialect);
myTemplateEngine.initialize();
}
public void setServerBase(String theServerBase) {
myServerBase = theServerBase;
}
private RuntimeResourceDefinition getResourceType(HttpServletRequest theReq) throws ServletException {
String resourceName = StringUtils.defaultString(theReq.getParameter(PARAM_RESOURCE));
RuntimeResourceDefinition def = myCtx.getResourceDefinition(resourceName);
if (def == null) {
throw new ServletException("Invalid resourceName: " + resourceName);
}
return def;
}
private void streamResponse(String theResourceName, String theContentType, HttpServletResponse theResp) throws IOException {
InputStream res = RestfulTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/" + theResourceName);
theResp.setContentType(theContentType);
IOUtils.copy(res, theResp.getOutputStream());
}
private enum ResultType {
RESOURCE, BUNDLE, TAGLIST, NONE
}
private void processAction(HttpServletRequest theReq, WebContext theContext) {
GenericClient client = (GenericClient) myCtx.newRestfulGenericClient(myServerBase);
client.setKeepResponses(true);
ResultType returnsResource;
long latency = 0;
String outcomeDescription = null;
try {
String method = theReq.getParameter("action");
String prettyParam = theReq.getParameter("pretty");
if ("true".equals(prettyParam)) {
client.setPrettyPrint(true);
} else if ("false".equals(prettyParam)) {
client.setPrettyPrint(false);
}
EncodingEnum encoding = getRequestEncoding(theReq);
client.setEncoding(encoding);
long start = System.currentTimeMillis();
if ("home".equals(method)) {
return;
} else if ("conformance".equals(method)) {
returnsResource = ResultType.RESOURCE;
client.conformance();
} else if ("read".equals(method)) {
RuntimeResourceDefinition def = getResourceType(theReq);
String id = StringUtils.defaultString(theReq.getParameter("id"));
if (StringUtils.isBlank(id)) {
theContext.getVariables().put("errorMsg", "No ID specified");
return;
}
returnsResource = ResultType.RESOURCE;
String versionId = StringUtils.defaultString(theReq.getParameter("vid"));
if (StringUtils.isBlank(versionId)) {
versionId = null;
outcomeDescription = "Read Resource";
} else {
outcomeDescription = "VRead Resource";
}
client.read(def.getImplementingClass(), new IdDt(def.getName(), id, versionId));
} else if ("get-tags".equals(method)) {
Class<? extends IResource> resType = null;
if (isNotBlank(theReq.getParameter(PARAM_RESOURCE))) {
RuntimeResourceDefinition def = getResourceType(theReq);
resType = def.getImplementingClass();
String id = theReq.getParameter("resource-tags-id");
if (isNotBlank(id)) {
String vid = theReq.getParameter("resource-tags-vid");
if (isNotBlank(vid)) {
client.getTags().forResource(resType, id, vid).execute();
} else {
client.getTags().forResource(resType, id).execute();
}
} else {
client.getTags().forResource(resType).execute();
}
} else {
client.getTags().execute();
}
returnsResource = ResultType.TAGLIST;
outcomeDescription = "Tag List";
} else if ("page".equals(method)) {
String url = defaultString(theReq.getParameter("page-url"));
if (!url.startsWith(myServerBase)) {
theContext.getVariables().put("errorMsg", "Invalid page URL: " + url);
return;
}
url = url.replace("&amp;", "&");
client.loadPage().url(url).execute();
returnsResource = ResultType.BUNDLE;
outcomeDescription = "Bundle Page";
} else if ("delete".equals(method)) {
RuntimeResourceDefinition def = getResourceType(theReq);
String id = StringUtils.defaultString(theReq.getParameter("resource-delete-id"));
if (StringUtils.isBlank(id)) {
theContext.getVariables().put("errorMsg", "No ID specified");
return;
}
returnsResource = ResultType.BUNDLE;
outcomeDescription = "Delete Resource";
client.delete(def.getImplementingClass(), new IdDt(id));
} else if ("history-resource".equals(method) || "history-server".equals(method)) {
String id = null;
Class<? extends IResource> type = null; // def.getImplementingClass();
if (!"history-server".equals(method)) {
RuntimeResourceDefinition def = getResourceType(theReq);
type = def.getImplementingClass();
id = StringUtils.defaultString(theReq.getParameter("resource-history-id"));
if (StringUtils.isBlank(id)) {
if ("history-instance".equals(method)) {
theContext.getVariables().put("errorMsg", "No ID specified");
return;
} else {
id = null;
}
}
}
DateTimeDt since = null;
String sinceStr = theReq.getParameter("since");
if (isNotBlank(sinceStr)) {
since = new DateTimeDt(sinceStr);
}
Integer limit = null;
String limitStr = theReq.getParameter("limit");
if (isNotBlank(limitStr)) {
limit = Integer.parseInt(limitStr);
}
returnsResource = ResultType.BUNDLE;
outcomeDescription = "Resource History";
client.history(type, id, since, limit);
} else if ("create".equals(method) || "validate".equals(method)) {
boolean validate = "validate".equals(method);
String body = validate ? theReq.getParameter("resource-validate-body") : theReq.getParameter("resource-create-body");
if (isBlank(body)) {
theContext.getVariables().put("errorMsg", "No message body specified");
return;
}
body = body.trim();
IResource resource;
try {
if (body.startsWith("{")) {
resource = myCtx.newJsonParser().parseResource(body);
} else if (body.startsWith("<")) {
resource = myCtx.newXmlParser().parseResource(body);
} else {
theContext.getVariables().put("errorMsg", "Message body does not appear to be a valid FHIR resource instance document. Body should start with '<' (for XML encoding) or '{' (for JSON encoding).");
return;
}
} catch (DataFormatException e) {
ourLog.warn("Failed to parse resource", e);
theContext.getVariables().put("errorMsg", "Failed to parse message body. Error was: " + e.getMessage());
return;
}
if (validate) {
client.validate(resource);
outcomeDescription = "Validate Resource";
} else {
String id = theReq.getParameter("resource-create-id");
if (isNotBlank(id)) {
outcomeDescription = "Update Resource";
client.update(id, resource);
} else {
outcomeDescription = "Create Resource";
client.create(resource);
}
}
returnsResource = ResultType.RESOURCE;
} else if ("search".equals(method)) {
IUntypedQuery search = client.search();
IQuery query;
if (isNotBlank(theReq.getParameter("resource"))) {
query = search.forResource(getResourceType(theReq).getImplementingClass());
} else {
query = search.forAllResources();
}
outcomeDescription = "Search for Resources";
int paramIdx = -1;
while (true) {
paramIdx++;
String nextName = theReq.getParameter("param." + paramIdx + ".name");
if (isBlank(nextName)) {
break;
}
String nextType = theReq.getParameter("param." + paramIdx + ".type");
StringBuilder b = new StringBuilder();
for (int i = 0; i < 100; i++) {
b.append(defaultString(theReq.getParameter("param." + paramIdx + "." + i)));
}
String paramValue = b.toString();
if (isBlank(paramValue)) {
continue;
}
if ("token".equals(nextType)) {
if (paramValue.length() < 2) {
continue;
}
}
// if ("xml".equals(theReq.getParameter("encoding"))) {
// query.encodedXml();
// }else if ("json".equals(theReq.getParameter("encoding"))) {
// query.encodedJson();
// }
query.where(new StringParam(nextName).matches().value(paramValue));
}
String[] incValues = theReq.getParameterValues(Constants.PARAM_INCLUDE);
if (incValues != null) {
for (String next : incValues) {
if (isNotBlank(next)) {
query.include(new Include(next));
}
}
}
String limit = theReq.getParameter("resource-search-limit");
if (isNotBlank(limit)) {
if (!limit.matches("[0-9]+")) {
theContext.getVariables().put("errorMsg", "Search limit must be a numeric value.");
return;
}
query.limitTo(Integer.parseInt(limit));
}
query.execute();
returnsResource = ResultType.BUNDLE;
} else {
theContext.getVariables().put("errorMsg", "Invalid action: " + method);
return;
}
latency = System.currentTimeMillis() - start;
} catch (DataFormatException e) {
ourLog.error("Failed to invoke method", e);
returnsResource = ResultType.NONE;
} catch (BaseServerResponseException e) {
ourLog.error("Failed to invoke method", e);
returnsResource = ResultType.NONE;
} catch (Exception e) {
ourLog.error("Failure during processing", e);
returnsResource = ResultType.NONE;
}
try {
HttpRequestBase lastRequest = client.getLastRequest();
String requestBody = null;
String requestSyntaxHighlighterClass = null;
if (lastRequest instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest lastEERequest = (HttpEntityEnclosingRequest) lastRequest;
HttpEntity lastEE = lastEERequest.getEntity();
if (lastEE.isRepeatable()) {
StringWriter requestCapture = new StringWriter();
lastEE.writeTo(new WriterOutputStream(requestCapture, "UTF-8"));
requestBody = requestCapture.toString();
ContentType ct = ContentType.get(lastEE);
String mimeType = ct.getMimeType();
EncodingEnum ctEnum = EncodingEnum.forContentType(mimeType);
if (ctEnum == null) {
requestSyntaxHighlighterClass = "brush: plain";
} else {
switch (ctEnum) {
case JSON:
requestSyntaxHighlighterClass = "brush: jscript";
break;
case XML:
default:
requestSyntaxHighlighterClass = "brush: xml";
break;
}
}
}
}
String resultSyntaxHighlighterClass;
String requestUrl = lastRequest != null ? lastRequest.getURI().toASCIIString() : null;
String action = client.getLastRequest() != null ? client.getLastRequest().getMethod() : null;
String resultStatus = client.getLastResponse() != null ? client.getLastResponse().getStatusLine().toString() : null;
String resultBody = client.getLastResponseBody();
HttpResponse lastResponse = client.getLastResponse();
ContentType ct = lastResponse != null ? ContentType.get(lastResponse.getEntity()) : null;
String mimeType = ct != null ? ct.getMimeType() : null;
EncodingEnum ctEnum = EncodingEnum.forContentType(mimeType);
String narrativeString = "";
StringBuilder resultDescription = new StringBuilder();
Bundle bundle = null;
if (ctEnum == null) {
resultSyntaxHighlighterClass = "brush: plain";
resultDescription.append("Non-FHIR response");
} else {
switch (ctEnum) {
case JSON:
resultSyntaxHighlighterClass = "brush: jscript";
if (returnsResource == ResultType.RESOURCE) {
narrativeString = parseNarrative(ctEnum, resultBody);
resultDescription.append("JSON resource");
} else if (returnsResource == ResultType.BUNDLE) {
resultDescription.append("JSON bundle");
bundle = myCtx.newJsonParser().parseBundle(resultBody);
}
break;
case XML:
default:
resultSyntaxHighlighterClass = "brush: xml";
if (returnsResource == ResultType.RESOURCE) {
narrativeString = parseNarrative(ctEnum, resultBody);
resultDescription.append("XML resource");
} else if (returnsResource == ResultType.BUNDLE) {
resultDescription.append("XML bundle");
bundle = myCtx.newXmlParser().parseBundle(resultBody);
}
break;
}
}
resultDescription.append(" (").append(resultBody.length() + " bytes)");
Header[] requestHeaders = lastRequest != null ? applyHeaderFilters(lastRequest.getAllHeaders()) : new Header[0];
Header[] responseHeaders = lastResponse != null ? applyHeaderFilters(lastResponse.getAllHeaders()) : new Header[0];
theContext.setVariable("outcomeDescription", outcomeDescription);
theContext.setVariable("resultDescription", resultDescription.toString());
theContext.setVariable("action", action);
theContext.setVariable("bundle", bundle);
theContext.setVariable("resultStatus", resultStatus);
theContext.setVariable("requestUrl", requestUrl);
String requestBodyText = format(requestBody, ctEnum);
theContext.setVariable("requestBody", requestBodyText);
theContext.setVariable("requestSyntaxHighlighterClass", requestSyntaxHighlighterClass);
String resultBodyText = format(resultBody, ctEnum);
theContext.setVariable("resultBody", resultBodyText);
theContext.setVariable("resultBodyIsLong", resultBodyText.length() > 1000);
theContext.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
theContext.setVariable("requestHeaders", requestHeaders);
theContext.setVariable("responseHeaders", responseHeaders);
theContext.setVariable("narrative", narrativeString);
theContext.setVariable("latencyMs", latency);
} catch (Exception e) {
ourLog.error("Failure during processing", e);
theContext.getVariables().put("errorMsg", "Error during processing: " + e.getMessage());
}
}
private String format(String theResultBody, EncodingEnum theEncodingEnum) {
String str = StringEscapeUtils.escapeHtml4(theResultBody);
if (str == null || theEncodingEnum == null) {
return str;
}
StringBuilder b = new StringBuilder();
if (theEncodingEnum == EncodingEnum.JSON) {
boolean inValue = false;
boolean inQuote = false;
for (int i = 0; i < str.length(); i++) {
char prevChar = (i > 0) ? str.charAt(i-1): ' ';
char nextChar = str.charAt(i);
char nextChar2 = (i + 1) < str.length() ? str.charAt(i + 1) : ' ';
char nextChar3 = (i + 2) < str.length() ? str.charAt(i + 2) : ' ';
char nextChar4 = (i + 3) < str.length() ? str.charAt(i + 3) : ' ';
char nextChar5 = (i + 4) < str.length() ? str.charAt(i + 4) : ' ';
char nextChar6 = (i + 5) < str.length() ? str.charAt(i + 5) : ' ';
if (inQuote) {
b.append(nextChar);
if (prevChar != '\\' && nextChar == '&' && nextChar2 == 'q' && nextChar3 == 'u' && nextChar4 == 'o' && nextChar5 == 't' && nextChar6 == ';') {
b.append("quot;</span>");
i += 5;
inQuote = false;
}else if (nextChar == '\\' && nextChar2 == '"') {
b.append("quot;</span>");
i += 5;
inQuote = false;
}
} else {
if (nextChar == ':') {
inValue = true;
b.append(nextChar);
}else if (nextChar == '[' || nextChar == '[') {
b.append("<span class='hlControl'>");
b.append(nextChar);
b.append("</span>");
inValue = false;
}else if (nextChar == '}' || nextChar == '}' || nextChar == ',') {
b.append("<span class='hlControl'>");
b.append(nextChar);
b.append("</span>");
inValue = false;
} else if (nextChar == '&' && nextChar2 == 'q' && nextChar3 == 'u' && nextChar4 == 'o' && nextChar5 == 't' && nextChar6 == ';') {
if (inValue) {
b.append("<span class='hlQuot'>&quot;");
}else {
b.append("<span class='hlTagName'>&quot;");
}
inQuote = true;
i += 5;
}else if (nextChar == ':') {
b.append("<span class='hlControl'>");
b.append(nextChar);
b.append("</span>");
inValue = true;
} else {
b.append(nextChar);
}
}
}
} else {
boolean inQuote = false;
boolean inTag = false;
for (int i = 0; i < str.length(); i++) {
char nextChar = str.charAt(i);
char nextChar2 = (i + 1) < str.length() ? str.charAt(i + 1) : ' ';
char nextChar3 = (i + 2) < str.length() ? str.charAt(i + 2) : ' ';
char nextChar4 = (i + 3) < str.length() ? str.charAt(i + 3) : ' ';
char nextChar5 = (i + 4) < str.length() ? str.charAt(i + 4) : ' ';
char nextChar6 = (i + 5) < str.length() ? str.charAt(i + 5) : ' ';
if (inQuote) {
b.append(nextChar);
if (nextChar == '&' && nextChar2 == 'q' && nextChar3 == 'u' && nextChar4 == 'o' && nextChar5 == 't' && nextChar6 == ';') {
b.append("quot;</span>");
i += 5;
inQuote = false;
}
} else if (inTag) {
if (nextChar == '&' && nextChar2 == 'g' && nextChar3 == 't' && nextChar4 == ';') {
b.append("</span><span class='hlControl'>&gt;</span>");
inTag = false;
i += 3;
} else if (nextChar == ' ') {
b.append("</span><span class='hlAttr'>");
b.append(nextChar);
} else if (nextChar == '&' && nextChar2 == 'q' && nextChar3 == 'u' && nextChar4 == 'o' && nextChar5 == 't' && nextChar6 == ';') {
b.append("<span class='hlQuot'>&quot;");
inQuote = true;
i += 5;
} else {
b.append(nextChar);
}
} else {
if (nextChar == '&' && nextChar2 == 'l' && nextChar3 == 't' && nextChar4 == ';') {
b.append("<span class='hlControl'>&lt;</span><span class='hlTagName'>");
inTag = true;
i += 3;
} else {
b.append(nextChar);
}
}
}
}
return b.toString();
}
private EncodingEnum getRequestEncoding(HttpServletRequest theReq) {
EncodingEnum encoding;
if ("xml".equals(theReq.getParameter("encoding"))) {
encoding = EncodingEnum.XML;
} else if ("json".equals(theReq.getParameter("encoding"))) {
encoding = (EncodingEnum.JSON);
} else {
encoding = null;
}
return encoding;
}
@Override
protected void doGet(HttpServletRequest theReq, HttpServletResponse theResp) throws ServletException, IOException {
if (DEBUGMODE) {
myTemplateEngine.getCacheManager().clearAllCaches();
}
try {
ourLog.trace("RequestURI: {}", theReq.getPathInfo());
String resName = theReq.getPathInfo().substring(1);
if (myStaticResources.containsKey(resName)) {
streamResponse(resName, myStaticResources.get(resName), theResp);
return;
}
IGenericClient client = myCtx.newRestfulGenericClient(myServerBase);
Conformance conformance = client.conformance();
WebContext ctx = new WebContext(theReq, theResp, theReq.getServletContext(), theReq.getLocale());
Map<String, Number> resourceCounts = new HashMap<String, Number>();
long total = 0;
for (Rest nextRest : conformance.getRest()) {
for (RestResource nextResource : nextRest.getResource()) {
List<ExtensionDt> exts = nextResource.getUndeclaredExtensionsByUrl(RESOURCE_COUNT_EXT_URL);
if (exts != null && exts.size() > 0) {
Number nextCount = ((DecimalDt) (exts.get(0).getValue())).getValueAsNumber();
resourceCounts.put(nextResource.getType().getValue(), nextCount);
total += nextCount.longValue();
}
}
}
if (total > 0) {
for (Rest nextRest : conformance.getRest()) {
Collections.sort(nextRest.getResource(), new Comparator<RestResource>() {
@Override
public int compare(RestResource theO1, RestResource theO2) {
DecimalDt count1 = new DecimalDt();
List<ExtensionDt> count1exts = theO1.getUndeclaredExtensionsByUrl(RESOURCE_COUNT_EXT_URL);
if (count1exts != null && count1exts.size() > 0) {
count1 = (DecimalDt) count1exts.get(0).getValue();
}
DecimalDt count2 = new DecimalDt();
List<ExtensionDt> count2exts = theO2.getUndeclaredExtensionsByUrl(RESOURCE_COUNT_EXT_URL);
if (count2exts != null && count2exts.size() > 0) {
count2 = (DecimalDt) count2exts.get(0).getValue();
}
int retVal = count2.compareTo(count1);
if (retVal == 0) {
retVal = theO1.getType().getValue().compareTo(theO2.getType().getValue());
}
return retVal;
}
});
}
}
ctx.setVariable("resourceCounts", resourceCounts);
ctx.setVariable("conf", conformance);
ctx.setVariable("base", myServerBase);
String resourceName = defaultString(theReq.getParameter(PARAM_RESOURCE));
ctx.setVariable("resourceName", resourceName);
ctx.setVariable("jsonEncodedConf", myCtx.newJsonParser().encodeResourceToString(conformance));
addStandardVariables(ctx, theReq.getParameterMap());
if (isNotBlank(theReq.getParameter("action"))) {
processAction(theReq, ctx);
}
if (isNotBlank(resourceName)) {
RuntimeResourceDefinition def = myCtx.getResourceDefinition(resourceName);
TreeSet<String> includes = new TreeSet<String>();
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != SearchParamTypeEnum.REFERENCE) {
continue;
}
String nextPath = nextSpDef.getPath();
includes.add(nextPath);
}
ctx.setVariable("includes", includes);
if (isNotBlank(theReq.getParameter("update-id"))) {
String updateId = theReq.getParameter("update-id");
String updateVid = defaultIfEmpty(theReq.getParameter("update-vid"), null);
IResource updateResource = client.read(def.getImplementingClass(), new IdDt(resourceName, updateId, updateVid));
EncodingEnum encoding = getRequestEncoding(theReq);
if (encoding == null) {
encoding = EncodingEnum.XML;
}
String updateResourceString = encoding.newParser(myCtx).setPrettyPrint(true).encodeResourceToString(updateResource);
ctx.setVariable("updateResource", updateResourceString);
ctx.setVariable("updateResourceId", updateId);
}
}
theResp.setContentType("text/html");
theResp.setCharacterEncoding("UTF-8");
myTemplateEngine.process(theReq.getPathInfo(), ctx, theResp.getWriter());
} catch (Exception e) {
ourLog.error("Failed to respond", e);
theResp.sendError(500, e.getMessage());
}
}
private void addStandardVariables(WebContext theCtx, Map<String, String[]> theParameterMap) {
addStandardVariable(theCtx, theParameterMap, "encoding");
addStandardVariable(theCtx, theParameterMap, "pretty");
}
private void addStandardVariable(WebContext theCtx, Map<String, String[]> theParameterMap, String key) {
if (theParameterMap.containsKey(key) && theParameterMap.get(key).length > 0) {
theCtx.setVariable(key, theParameterMap.get(key)[0]);
}
}
private Header[] applyHeaderFilters(Header[] theAllHeaders) {
if (myFilterHeaders == null || myFilterHeaders.isEmpty()) {
return theAllHeaders;
}
ArrayList<Header> retVal = new ArrayList<Header>();
for (Header next : theAllHeaders) {
if (!myFilterHeaders.contains(next.getName().toLowerCase())) {
retVal.add(next);
}
}
return retVal.toArray(new Header[retVal.size()]);
}
/**
* If set, the headers named here will be stripped from requests/responses before they are displayed to the user.
* This can be used, for instance, to filter out "Authorization" headers. Note that names are not case sensitive.
*/
public void setFilterHeaders(String... theHeaderNames) {
myFilterHeaders = new HashSet<String>();
if (theHeaderNames != null) {
for (String next : theHeaderNames) {
myFilterHeaders.add(next.toLowerCase());
}
}
}
private String parseNarrative(EncodingEnum theCtEnum, String theResultBody) {
try {
IResource resource = theCtEnum.newParser(myCtx).parseResource(theResultBody);
String retVal = resource.getText().getDiv().getValueAsString();
return StringUtils.defaultString(retVal);
} catch (Exception e) {
ourLog.error("Failed to parse resource", e);
return "";
}
}
private interface ConformanceClient extends IBasicClient {
@Metadata
Conformance getConformance();
}
private final class ProfileResourceResolver implements IResourceResolver {
@Override
public String getName() {
return getClass().getCanonicalName();
}
@Override
public InputStream getResourceAsStream(TemplateProcessingParameters theTemplateProcessingParameters, String theName) {
ourLog.debug("Loading template: {}", theName);
if ("/".equals(theName)) {
return RestfulTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/RestfulTester.html");
}
if (PUBLIC_TESTER_RESULT_HTML.equals(theName)) {
return RestfulTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/PublicTesterResult.html");
}
return null;
}
}
}

View File

@ -1,60 +0,0 @@
A.selectedFunctionLink {
text-decoration: none;
background: #E0FFE0;
border: 1px #80C080 solid;
color: #005000;
}
BODY {
font-family: sans-serif;
}
SPAN.headerName {
color: #505080;
}
SPAN.headerValue {
color: #70A070;
}
DIV.bodyHeaderBlock {
background-color: #E0E0E0;
margin-top: 5px;
border-radius: 5px;
padding: 5px;
}
DIV.textareaWrapper {
position:relative;
height:100%;
width:100%;
}
DIV.textareaWrapper TEXTAREA {
width:95%;
overflow: scroll;
}
TABLE.propertyTable {
margin-left: 4px;
width: 95%;
}
TD.propertyKeyCell {
background-color: #E0E0FF;
border-radius: 3px;
padding: 3px;
width: 100px;
}
TD.testerNameCell {
background-color: #E0FFE0;
border-radius: 3px;
padding: 3px;
}
.syntaxhighlighter {
font-size: 0.85em !important;
min-height: 1.4em;
max-width: 800px;
}

View File

@ -1,159 +0,0 @@
<!DOCTYPE html>
<!--/*
************************************************************
This file is a Thymeleaf template for the
************************************************************
*/-->
<html>
<head>
<script type="text/javascript">
var serverBase = "<th:block th:text="${base}"/>";
var conformance = <th:block th:utext="${jsonEncodedConf}"/>;
</script>
<script type="text/javascript" src="jquery-2.1.0.min.js"></script>
<script type="text/javascript" src="PublicTester.js"></script>
<link rel="stylesheet" type="text/css" href="PublicTester.css"/>
<meta charset="UTF-8"/>
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript" src="minify.json.js"></script>
</head>
<body onload="selectResourceType();">
<table border="0" width="100%">
<tr>
<td align="left"><img src="hapi_fhir_banner.png"/></td>
<td align="right"><img src="hapi_fhir_banner_right.png"/></td>
</tr>
</table>
<div class="bodyHeaderBlock">
This is a RESTful server tester, which can be used to send requests to, and receive responses
from the server at the following URL:<br/>
<a href="http://foo.com/fhir" th:href="${base}"><th:block th:text="${base}">http://foo.com/fhir</th:block></a>
</div>
<table border="0" width="100%" cellpadding="0" cellspacing="0" style="margin-top: 4px;">
<tr>
<td width="29%" valign="top">
<div class="bodyHeaderBlock">
Software Details
</div>
<table border="0" class="propertyTable">
<tr>
<td class="propertyKeyCell">Software</td>
<td th:text="${conf.software.name}">HAPI Restful Server</td>
</tr>
<tr>
<td class="propertyKeyCell">Version</td>
<td th:text="${conf.software.version}">1.1.1</td>
</tr>
</table>
<div class="bodyHeaderBlock">
Request Configuration
</div>
<table border="0" class="propertyTable">
<tr>
<td class="propertyKeyCell">Encoding</td>
<td>
<select id="configEncoding" th:switch="${configEncoding}">
<th:block th:case="'xml'">
<option value="">(default)</option>
<option value="xml" selected="selected">XML</option>
<option value="json">JSON</option>
</th:block>
<th:block th:case="'json'">
<option value="">(default)</option>
<option value="xml">XML</option>
<option value="json" selected="selected">JSON</option>
</th:block>
<th:block th:case="*">
<option value="" selected="selected">(default)</option>
<option value="xml">XML</option>
<option value="json">JSON</option>
</th:block>
</select>
</td>
</tr>
<tr>
<td class="propertyKeyCell">Pretty Printing</td>
<td th:switch="${configPretty}">
<input th:case="'false'" type="checkbox" id="configPretty"/>
<input th:case="*" type="checkbox" id="configPretty" checked="checked"/>
</td>
</tr>
</table>
</td>
<td width="1%"/>
<td width="70%" valign="top">
<th:block th:each="rest : ${conf.rest}">
<div class="bodyHeaderBlock">
RESTful Server
</div>
<table border="0" th:id="systemExpando" class="propertyTable">
<tr>
<td valign="top" class="propertyKeyCell">Supports operations:</td>
<td valign="top">
<a th:onclick="'displayConformance(this, \'systemExpando\'); return false;'" href="#">conformance</a>
<th:span th:each="operation : ${rest.operation}">
<th:block th:switch="${operation.code.value}">
<span th:case="*" th:text="${operation.code.value}"/>
</th:block>
</th:span>
</td>
</tr>
</table>
<div class="bodyHeaderBlock">
Resources
</div>
<table border="0" th:id="systemExpando" class="propertyTable">
<tr>
<td valign="top" class="propertyKeyCell">Select Resource:</td>
<td valign="top">
<select id="configResource" onchange="selectResourceType();">
<th:block th:each="resource, resIterStat : ${rest.resource}">
<option th:value="${resource.type.valueAsString}" th:text="${resource.type.valueAsString}"/>
</th:block>
</select>
</td>
</tr>
</table>
<div th:each="resource, resIterStat : ${rest.resource}" th:with="expandoId='resExpando'+${resIterStat.count}" th:id="'res' + ${resource.type.valueAsString}" class="resourceTypeContainer" style="display:none;">
<div class="bodyHeaderBlock">
Resource: <th:block th:text="${resource.type.valueAsString}"/>
</div>
<table border="0" th:id="${expandoId}" class="propertyTable">
<tr>
<td valign="top" class="propertyKeyCell">Supports operations:</td>
<td valign="top">
<th:span th:each="operation : ${resource.operation}">
<th:block th:switch="${operation.code.value}">
<a th:case="'read'" href="#" th:onclick="'displayRead(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">read</a>
<a th:case="'vread'" href="#" th:onclick="'displayVRead(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">vread</a>
<a th:case="'search-type'" href="#" th:onclick="'displaySearchType(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">search-type</a>
<a th:case="'create'" href="#" th:onclick="'displayCreate(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">create</a>
<a th:case="'update'" href="#" th:onclick="'displayUpdate(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">update</a>
<a th:case="'validate'" href="#" th:onclick="'displayValidate(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">validate</a>
<a th:case="'delete'" href="#" th:onclick="'displayDelete(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">delete</a>
<a th:case="'history-instance'" href="#" th:onclick="'displayHistoryInstance(this, \'' + ${expandoId} + '\', \'' + ${resource.type.valueAsString} + '\'); return false;'">history-instance</a>
<span th:case="*" href="#" th:text="${operation.code.value}"/>
</th:block>
</th:span>
</td>
</tr>
</table>
</div>
</th:block>
</td>
</tr>
</table>
</body>
</html>

View File

@ -1,360 +0,0 @@
var uniqueIdSeed = 1;
function addConfigElementsToForm(theForm) {
var encoding = document.getElementById('configEncoding');
var pretty = document.getElementById('configPretty');
var newEncoding = document.createElement("input");
newEncoding.type='hidden';
newEncoding.name='configEncoding';
newEncoding.value = encoding.value;
theForm.appendChild(newEncoding);
var newPretty = document.createElement("input");
newPretty.type='hidden';
newPretty.name='configPretty';
if (pretty.checked) {
newPretty.value='on';
}
newPretty.checked = pretty.checked;
theForm.appendChild(newPretty);
}
function appendSearchParam(formElement, searchParam) {
var inputId = newUniqueId();
if (searchParam.type && searchParam.type == 'token') {
formElement.append(
$('<input />', { name: 'param.token.1.' + searchParam.name, placeholder: 'system/namespace', type: 'text', id: inputId }),
$('<input />', { name: 'param.token.2.' + searchParam.name, placeholder: 'value', type: 'text', id: inputId }),
$('<label for="' + inputId + '">' + searchParam.name + '</input>')
);
} else {
formElement.append(
$('<input />', { name: 'param.string.' + searchParam.name, placeholder: searchParam.name, type: 'text', id: inputId }),
$('<label for="' + inputId + '">' + searchParam.name + '</input>')
);
}
}
function appendSearchParamExtension(extension) {
}
/** Hide any currently displayed tester form */
function clearCurrentForm(postCompleteFunction) {
/* $('.testerNameRow').each().fadeOut(500).promise().then(function(){
if (postCompleteFunction != null) {
$('.testerNameRow').each().remove();
postCompleteFunction();
postCompleteFunction = null;
}
}); */
var current = $('.testerNameRow');
if (current.length == 0) {
postCompleteFunction();
} else {
current.first().fadeOut(300, function() {
current.first().remove();
clearCurrentForm(postCompleteFunction);
});
}
}
/** Create a tester form for the 'read' method */
function displayConformance(button, expandoTr) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Conformance</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "addConfigElementsToForm(this);" }).append(
$('<input />', { name: 'method', value: 'conformance', type: 'hidden' }),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
function minifyTextarea(self) {
var value = value;
value = value.replace(/[\u00A0\u1680\u180e\u2000-\u2009\u200a\u200b\u202f\u205f\u3000]/g,' ');
//value = JSON.minify(value);
$('#textarea').val(value);
return addConfigElementsToForm(self);
}
/** Create a tester form for the 'read' method */
function displayCreate(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Create</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "minifyTextarea(this);" }).append(
$('<input />', { name: 'method', value: 'create', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<div class="textareaWrapper">').append(
$('<textarea />', { id: 'textarea', name: 'resource', rows: 10, style: 'white-space: nowrap;' })
),
$('<br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
/** Create a tester form for the 'delete' method */
function displayDelete(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Delete</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "addConfigElementsToForm(this);" }).append(
$('<input />', { name: 'method', value: 'delete', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<input />', { name: 'id', placeholder: 'Resource ID', type: 'text' }),
$('<br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
/** Create a tester form for the 'read' method */
function displayUpdate(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Update</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "minifyTextarea(this);" }).append(
$('<input />', { name: 'method', value: 'update', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<input />', { name: 'id', placeholder: 'Resource ID', type: 'text' }),
$('<textarea />', { id: 'textarea', name: 'resource', cols: 100, rows: 10, style: 'white-space: nowrap;' }),
$('<br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
/** Create a tester form for the 'search' method */
function displaySearchType(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
// Add a search form for the default (no parameter) search, which should
// return all resources of the given type
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Search by Type</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "addConfigElementsToForm(this);" }).append(
$('<input />', { name: 'method', value: 'searchType', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<span>All Resources of Type</span><br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
// Loop through each supported search parameter and add a search form for it
conformance.rest.forEach(function(rest){
rest.resource.forEach(function(restResource){
if (restResource.type == resourceName) {
if (restResource.searchParam) {
var paramIndex = 0;
restResource.searchParam.forEach(function(searchParam){
var formElement = $('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "addConfigElementsToForm(this);" });
formElement.append(
$('<input />', { name: 'method', value: 'searchType', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' })
)
if (searchParam.documentation && searchParam.documentation.length > 0) {
formElement.append(
$('<span>' + searchParam.documentation + '<br /></span>')
);
}
appendSearchParam(formElement, searchParam);
// http://hl7api.sourceforge.net/hapi-fhir/extensions.xml#additionalParam
if (restResource._searchParam && restResource._searchParam[paramIndex] != null) {
if (restResource._searchParam[paramIndex].extension) {
appendSearchParamExtension(restResource._searchParam[paramIndex].extension);
}
}
formElement.append(
$('<br />')
);
formElement.append(
$('<input />', { type: 'submit', value: 'Submit' })
);
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Search by Type</td>'),
$('<td />').append(
formElement
)
)
);
paramIndex++;
});
}
}
});
});
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
/** Create a tester form for the 'instance-history' method */
function displayHistoryInstance(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Read</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "addConfigElementsToForm(this);" }).append(
$('<input />', { name: 'method', value: 'history-instance', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<input />', { name: 'id', placeholder: 'Resource ID', type: 'text' }),
$('<br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
/** Create a tester form for the 'read' method */
function displayRead(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Read</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "addConfigElementsToForm(this);" }).append(
$('<input />', { name: 'method', value: 'read', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<input />', { name: 'id', placeholder: 'Resource ID', type: 'text' }),
$('<br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
/** Create a tester form for the 'read' method */
function displayValidate(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Validate</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "minifyTextarea(this);" }).append(
$('<input />', { name: 'method', value: 'validate', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<textarea />', { id: 'textarea', name: 'resource', cols: 100, rows: 10, style: 'white-space: nowrap;' }),
$('<br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
/** Create a tester form for the 'read' method */
function displayVRead(button, expandoTr, resourceName) {
highlightSelectedLink(button);
var postCompleteFunction = function() {
$('#' + expandoTr).append(
$('<tr class="testerNameRow" style="display: none;" />').append(
$('<td class="testerNameCell">Read</td>'),
$('<td />').append(
$('<form/>', { action: 'PublicTesterResult.html', method: 'POST', onsubmit: "addConfigElementsToForm(this);" }).append(
$('<input />', { name: 'method', value: 'vread', type: 'hidden' }),
$('<input />', { name: 'resourceName', value: resourceName, type: 'hidden' }),
$('<input />', { name: 'id', placeholder: 'Resource ID', type: 'text' }),
$('<input />', { name: 'versionid', placeholder: 'Version ID', type: 'text' }),
$('<br />'),
$('<input />', { type: 'submit', value: 'Submit' })
)
)
)
);
showNewForm();
}
clearCurrentForm(postCompleteFunction);
}
function highlightSelectedLink(button) {
$('.selectedFunctionLink').each(function() {
$(this).removeClass('selectedFunctionLink');
});
button.className = 'selectedFunctionLink';
}
/** Generate a unique ID */
function newUniqueId() {
return "uid" + uniqueIdSeed++;
}
function selectResourceType() {
$('.resourceTypeContainer').each(function() {
$(this).hide();
});
var cr = document.getElementById('configResource');
var selected = cr.options[cr.selectedIndex].value;
$('#res' + selected).show();
}
/** Show a newly created tester form */
function showNewForm() {
var time = 0;
$('.testerNameRow').each(function() {
$(this).delay(time).fadeIn(200);
time += 200;
});
}

View File

@ -1,120 +0,0 @@
<!DOCTYPE html>
<!--/*
************************************************************
This file is a Thymeleaf template for the
************************************************************
*/-->
<html>
<head>
<script src="shCore.js" type="text/javascript"></script>
<script src="shBrushJScript.js" type="text/javascript"></script>
<script src="shBrushXml.js" type="text/javascript"></script>
<script src="shBrushPlain.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="shCore.css"/>
<link rel="stylesheet" type="text/css" href="shThemeDefault.css"/>
<script type="text/javascript" src="jquery-2.1.0.min.js"></script>
<script type="text/javascript" src="PublicTester.js"></script>
<script type="text/javascript">
var serverBase = "<th:block th:utext="${base}"/>";
</script>
<link rel="stylesheet" type="text/css" href="PublicTester.css"/>
</head>
<body>
<table border="0" width="100%">
<tr>
<td align="left"><img src="hapi_fhir_banner.png"/></td>
<td align="right"><img src="hapi_fhir_banner_right.png"/></td>
</tr>
</table>
<div class="bodyHeaderBlock">
Executed invocation against FHIR RESTful Server in
<th:block th:text="${latencyMs} + 'ms'"/>
</div>
<table border="0" width="100%" cellpadding="0" cellspacing="0" style="margin-top: 4px;">
<tr>
<td width="29%" valign="top">
<div class="bodyHeaderBlock">
Actions
</div>
<table border="0">
<tr>
<td class="propertyKeyCell">Something</td>
<td>Something</td>
</tr>
</table>
</td>
<td width="1%"/>
<td width="70%" valign="top">
<div class="bodyHeaderBlock">
Request
</div>
<table border="0" class="propertyTable">
<tr>
<td class="propertyKeyCell">Action</td>
<td th:text="${action}">GET</td>
</tr>
<tr>
<td class="propertyKeyCell">URL</td>
<td>
<a href="http://foo.com/fhir" th:href="${requestUrl}"><th:block th:text="${requestUrl}">http://foo.com/fhir</th:block></a>
</td>
</tr>
<tr > <!-- th:if="${not #lists.isEmpty(requestHeaders)}" -->
<td valign="top" class="propertyKeyCell">Headers</td>
<td valign="top">
<div th:each="header : ${requestHeaders}">
<span class="headerName" th:text="${header.name} + ': '"/>
<span class="headerValue" th:text="${header.value}"/>
</div>
</td>
</tr>
<tr th:if="${requestBody} != null">
<td valign="top" class="propertyKeyCell">Request Body</td>
<td valign="top"><pre th:text="${requestBody}" th:class="${requestSyntaxHighlighterClass}">{}</pre></td>
</tr>
</table>
<div class="bodyHeaderBlock">
Response
</div>
<table border="0" class="propertyTable">
<tr>
<td valign="top" class="propertyKeyCell">Status</td>
<td valign="top" th:text="${resultStatus}">HTTP 200 OK</td>
</tr>
<tr > <!-- th:if="${not #lists.isEmpty(responseHeaders)}" -->
<td valign="top" class="propertyKeyCell">Headers</td>
<td valign="top">
<div th:each="header : ${responseHeaders}">
<span class="headerName" th:text="${header.name} + ': '"/>
<span class="headerValue" th:text="${header.value}"/>
</div>
</td>
</tr>
<tr th:if="${!#strings.isEmpty(resultBody)}">
<td valign="top" class="propertyKeyCell">Result Body</td>
<td valign="top"><pre th:text="${resultBody}" th:class="${resultSyntaxHighlighterClass}">{}</pre></td>
</tr>
<tr th:if="${!#strings.isEmpty(narrative)}">
<td valign="top" class="propertyKeyCell">Result Narrative</td>
<td valign="top" th:utext="${narrative}"></td>
</tr>
</table>
</td>
</tr>
</table>
<script type="text/javascript">
SyntaxHighlighter.all();
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,11 +0,0 @@
/*!
http://www.JSON.org/json2.js
2009-09-29
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
*/
if(!this.JSON){this.JSON={}}(function(){function l(c){return c<10?'0'+c:c}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(c){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+l(this.getUTCMonth()+1)+'-'+l(this.getUTCDate())+'T'+l(this.getUTCHours())+':'+l(this.getUTCMinutes())+':'+l(this.getUTCSeconds())+'Z':null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(c){return this.valueOf()}}var o=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,p=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,h,m,r={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},j;function q(a){p.lastIndex=0;return p.test(a)?'"'+a.replace(p,function(c){var f=r[c];return typeof f==='string'?f:'\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function n(c,f){var a,e,d,i,k=h,g,b=f[c];if(b&&typeof b==='object'&&typeof b.toJSON==='function'){b=b.toJSON(c)}if(typeof j==='function'){b=j.call(f,c,b)}switch(typeof b){case'string':return q(b);case'number':return isFinite(b)?String(b):'null';case'boolean':case'null':return String(b);case'object':if(!b){return'null'}h+=m;g=[];if(Object.prototype.toString.apply(b)==='[object Array]'){i=b.length;for(a=0;a<i;a+=1){g[a]=n(a,b)||'null'}d=g.length===0?'[]':h?'[\n'+h+g.join(',\n'+h)+'\n'+k+']':'['+g.join(',')+']';h=k;return d}if(j&&typeof j==='object'){i=j.length;for(a=0;a<i;a+=1){e=j[a];if(typeof e==='string'){d=n(e,b);if(d){g.push(q(e)+(h?': ':':')+d)}}}}else{for(e in b){if(Object.hasOwnProperty.call(b,e)){d=n(e,b);if(d){g.push(q(e)+(h?': ':':')+d)}}}}d=g.length===0?'{}':h?'{\n'+h+g.join(',\n'+h)+'\n'+k+'}':'{'+g.join(',')+'}';h=k;return d}}if(typeof JSON.stringify!=='function'){JSON.stringify=function(c,f,a){var e;h='';m='';if(typeof a==='number'){for(e=0;e<a;e+=1){m+=' '}}else if(typeof a==='string'){m=a}j=f;if(f&&typeof f!=='function'&&(typeof f!=='object'||typeof f.length!=='number')){throw new Error('JSON.stringify');}return n('',{'':c})}}if(typeof JSON.parse!=='function'){JSON.parse=function(i,k){var g;function b(c,f){var a,e,d=c[f];if(d&&typeof d==='object'){for(a in d){if(Object.hasOwnProperty.call(d,a)){e=b(d,a);if(e!==undefined){d[a]=e}else{delete d[a]}}}}return k.call(c,f,d)}o.lastIndex=0;if(o.test(i)){i=i.replace(o,function(c){return'\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(i.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){g=eval('('+i+')');return typeof k==='function'?b({'':g},''):g}throw new SyntaxError('JSON.parse');}}}());

View File

@ -1,61 +0,0 @@
/*! JSON.minify()
v0.1 (c) Kyle Simpson
MIT License
*/
(function(global){
if (typeof global.JSON == "undefined" || !global.JSON) {
global.JSON = {};
}
global.JSON.minify = function(json) {
var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g,
in_string = false,
in_multiline_comment = false,
in_singleline_comment = false,
tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc
;
tokenizer.lastIndex = 0;
while (tmp = tokenizer.exec(json)) {
lc = RegExp.leftContext;
rc = RegExp.rightContext;
if (!in_multiline_comment && !in_singleline_comment) {
tmp2 = lc.substring(from);
if (!in_string) {
tmp2 = tmp2.replace(/(\n|\r|\s)*/g,"");
}
new_str[ns++] = tmp2;
}
from = tokenizer.lastIndex;
if (tmp[0] == "\"" && !in_multiline_comment && !in_singleline_comment) {
tmp2 = lc.match(/(\\)*$/);
if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) { // start of string with ", or unescaped " character found to end string
in_string = !in_string;
}
from--; // include " character in next catch
rc = json.substring(from);
}
else if (tmp[0] == "/*" && !in_string && !in_multiline_comment && !in_singleline_comment) {
in_multiline_comment = true;
}
else if (tmp[0] == "*/" && !in_string && in_multiline_comment && !in_singleline_comment) {
in_multiline_comment = false;
}
else if (tmp[0] == "//" && !in_string && !in_multiline_comment && !in_singleline_comment) {
in_singleline_comment = true;
}
else if ((tmp[0] == "\n" || tmp[0] == "\r") && !in_string && !in_multiline_comment && in_singleline_comment) {
in_singleline_comment = false;
}
else if (!in_multiline_comment && !in_singleline_comment && !(/\n|\r|\s/.test(tmp[0]))) {
new_str[ns++] = tmp[0];
}
}
new_str[ns++] = rc;
return new_str.join("");
};
})(this);

View File

@ -1,52 +0,0 @@
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
var keywords = 'break case catch continue ' +
'default delete do else false ' +
'for function if in instanceof ' +
'new null return super switch ' +
'this throw true try typeof var while with'
;
var r = SyntaxHighlighter.regexLib;
this.regexList = [
{ regex: r.multiLineDoubleQuotedString, css: 'string' }, // double quoted strings
{ regex: r.multiLineSingleQuotedString, css: 'string' }, // single quoted strings
{ regex: r.singleLineCComments, css: 'comments' }, // one line comments
{ regex: r.multiLineCComments, css: 'comments' }, // multiline comments
{ regex: /\s*#.*/gm, css: 'preprocessor' }, // preprocessor tags like #region and #endregion
{ regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' } // keywords
];
this.forHtmlScript(r.scriptScriptTags);
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['js', 'jscript', 'javascript'];
SyntaxHighlighter.brushes.JScript = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();

View File

@ -1,33 +0,0 @@
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['text', 'plain'];
SyntaxHighlighter.brushes.Plain = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();

View File

@ -1,69 +0,0 @@
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
function process(match, regexInfo)
{
var constructor = SyntaxHighlighter.Match,
code = match[0],
tag = new XRegExp('(&lt;|<)[\\s\\/\\?]*(?<name>[:\\w-\\.]+)', 'xg').exec(code),
result = []
;
if (match.attributes != null)
{
var attributes,
regex = new XRegExp('(?<name> [\\w:\\-\\.]+)' +
'\\s*=\\s*' +
'(?<value> ".*?"|\'.*?\'|\\w+)',
'xg');
while ((attributes = regex.exec(code)) != null)
{
result.push(new constructor(attributes.name, match.index + attributes.index, 'color1'));
result.push(new constructor(attributes.value, match.index + attributes.index + attributes[0].indexOf(attributes.value), 'string'));
}
}
if (tag != null)
result.push(
new constructor(tag.name, match.index + tag[0].indexOf(tag.name), 'keyword')
);
return result;
}
this.regexList = [
{ regex: new XRegExp('(\\&lt;|<)\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\](\\&gt;|>)', 'gm'), css: 'color2' }, // <![ ... [ ... ]]>
{ regex: SyntaxHighlighter.regexLib.xmlComments, css: 'comments' }, // <!-- ... -->
{ regex: new XRegExp('(&lt;|<)[\\s\\/\\?]*(\\w+)(?<attributes>.*?)[\\s\\/\\?]*(&gt;|>)', 'sg'), func: process }
];
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['xml', 'xhtml', 'xslt', 'html'];
SyntaxHighlighter.brushes.Xml = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();

View File

@ -1,226 +0,0 @@
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter a,
.syntaxhighlighter div,
.syntaxhighlighter code,
.syntaxhighlighter table,
.syntaxhighlighter table td,
.syntaxhighlighter table tr,
.syntaxhighlighter table tbody,
.syntaxhighlighter table thead,
.syntaxhighlighter table caption,
.syntaxhighlighter textarea {
-moz-border-radius: 0 0 0 0 !important;
-webkit-border-radius: 0 0 0 0 !important;
background: none !important;
border: 0 !important;
bottom: auto !important;
float: none !important;
height: auto !important;
left: auto !important;
line-height: 1.1em !important;
margin: 0 !important;
outline: 0 !important;
overflow: visible !important;
padding: 0 !important;
position: static !important;
right: auto !important;
text-align: left !important;
top: auto !important;
vertical-align: baseline !important;
width: auto !important;
box-sizing: content-box !important;
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
font-weight: normal !important;
font-style: normal !important;
font-size: 1em !important;
min-height: inherit !important;
min-height: auto !important;
}
.syntaxhighlighter {
width: 100% !important;
margin: 1em 0 1em 0 !important;
position: relative !important;
overflow: auto !important;
font-size: 1em !important;
}
.syntaxhighlighter.source {
overflow: hidden !important;
}
.syntaxhighlighter .bold {
font-weight: bold !important;
}
.syntaxhighlighter .italic {
font-style: italic !important;
}
.syntaxhighlighter .line {
white-space: pre !important;
}
.syntaxhighlighter table {
width: 100% !important;
}
.syntaxhighlighter table caption {
text-align: left !important;
padding: .5em 0 0.5em 1em !important;
}
.syntaxhighlighter table td.code {
width: 100% !important;
}
.syntaxhighlighter table td.code .container {
position: relative !important;
}
.syntaxhighlighter table td.code .container textarea {
box-sizing: border-box !important;
position: absolute !important;
left: 0 !important;
top: 0 !important;
width: 100% !important;
height: 100% !important;
border: none !important;
background: white !important;
padding-left: 1em !important;
overflow: hidden !important;
white-space: pre !important;
}
.syntaxhighlighter table td.gutter .line {
text-align: right !important;
padding: 0 0.5em 0 1em !important;
}
.syntaxhighlighter table td.code .line {
padding: 0 1em !important;
}
.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
padding-left: 0em !important;
}
.syntaxhighlighter.show {
display: block !important;
}
.syntaxhighlighter.collapsed table {
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar {
padding: 0.1em 0.8em 0em 0.8em !important;
font-size: 1em !important;
position: static !important;
width: auto !important;
height: auto !important;
}
.syntaxhighlighter.collapsed .toolbar span {
display: inline !important;
margin-right: 1em !important;
}
.syntaxhighlighter.collapsed .toolbar span a {
padding: 0 !important;
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar span a.expandSource {
display: inline !important;
}
.syntaxhighlighter .toolbar {
position: absolute !important;
right: 1px !important;
top: 1px !important;
width: 11px !important;
height: 11px !important;
font-size: 10px !important;
z-index: 10 !important;
}
.syntaxhighlighter .toolbar span.title {
display: inline !important;
}
.syntaxhighlighter .toolbar a {
display: block !important;
text-align: center !important;
text-decoration: none !important;
padding-top: 1px !important;
}
.syntaxhighlighter .toolbar a.expandSource {
display: none !important;
}
.syntaxhighlighter.ie {
font-size: .9em !important;
padding: 1px 0 1px 0 !important;
}
.syntaxhighlighter.ie .toolbar {
line-height: 8px !important;
}
.syntaxhighlighter.ie .toolbar a {
padding-top: 0px !important;
}
.syntaxhighlighter.printing .line.alt1 .content,
.syntaxhighlighter.printing .line.alt2 .content,
.syntaxhighlighter.printing .line.highlighted .number,
.syntaxhighlighter.printing .line.highlighted.alt1 .content,
.syntaxhighlighter.printing .line.highlighted.alt2 .content {
background: none !important;
}
.syntaxhighlighter.printing .line .number {
color: #bbbbbb !important;
}
.syntaxhighlighter.printing .line .content {
color: black !important;
}
.syntaxhighlighter.printing .toolbar {
display: none !important;
}
.syntaxhighlighter.printing a {
text-decoration: none !important;
}
.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
color: black !important;
}
.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
color: #008200 !important;
}
.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
color: blue !important;
}
.syntaxhighlighter.printing .keyword {
color: #006699 !important;
font-weight: bold !important;
}
.syntaxhighlighter.printing .preprocessor {
color: gray !important;
}
.syntaxhighlighter.printing .variable {
color: #aa7700 !important;
}
.syntaxhighlighter.printing .value {
color: #009900 !important;
}
.syntaxhighlighter.printing .functions {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .constants {
color: #0066cc !important;
}
.syntaxhighlighter.printing .script {
font-weight: bold !important;
}
.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
color: gray !important;
}
.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
color: red !important;
}
.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
color: black !important;
}

File diff suppressed because one or more lines are too long

View File

@ -1,328 +0,0 @@
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter a,
.syntaxhighlighter div,
.syntaxhighlighter code,
.syntaxhighlighter table,
.syntaxhighlighter table td,
.syntaxhighlighter table tr,
.syntaxhighlighter table tbody,
.syntaxhighlighter table thead,
.syntaxhighlighter table caption,
.syntaxhighlighter textarea {
-moz-border-radius: 0 0 0 0 !important;
-webkit-border-radius: 0 0 0 0 !important;
background: none !important;
border: 0 !important;
bottom: auto !important;
float: none !important;
height: auto !important;
left: auto !important;
line-height: 1.1em !important;
margin: 0 !important;
outline: 0 !important;
overflow: visible !important;
padding: 0 !important;
position: static !important;
right: auto !important;
text-align: left !important;
top: auto !important;
vertical-align: baseline !important;
width: auto !important;
box-sizing: content-box !important;
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
font-weight: normal !important;
font-style: normal !important;
font-size: 1em !important;
min-height: inherit !important;
min-height: auto !important;
}
.syntaxhighlighter {
width: 100% !important;
margin: 1em 0 1em 0 !important;
position: relative !important;
overflow: auto !important;
font-size: 1em !important;
}
.syntaxhighlighter.source {
overflow: hidden !important;
}
.syntaxhighlighter .bold {
font-weight: bold !important;
}
.syntaxhighlighter .italic {
font-style: italic !important;
}
.syntaxhighlighter .line {
white-space: pre !important;
}
.syntaxhighlighter table {
width: 100% !important;
}
.syntaxhighlighter table caption {
text-align: left !important;
padding: .5em 0 0.5em 1em !important;
}
.syntaxhighlighter table td.code {
width: 100% !important;
}
.syntaxhighlighter table td.code .container {
position: relative !important;
}
.syntaxhighlighter table td.code .container textarea {
box-sizing: border-box !important;
position: absolute !important;
left: 0 !important;
top: 0 !important;
width: 100% !important;
height: 100% !important;
border: none !important;
background: white !important;
padding-left: 1em !important;
overflow: hidden !important;
white-space: pre !important;
}
.syntaxhighlighter table td.gutter .line {
text-align: right !important;
padding: 0 0.5em 0 1em !important;
}
.syntaxhighlighter table td.code .line {
padding: 0 1em !important;
}
.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
padding-left: 0em !important;
}
.syntaxhighlighter.show {
display: block !important;
}
.syntaxhighlighter.collapsed table {
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar {
padding: 0.1em 0.8em 0em 0.8em !important;
font-size: 1em !important;
position: static !important;
width: auto !important;
height: auto !important;
}
.syntaxhighlighter.collapsed .toolbar span {
display: inline !important;
margin-right: 1em !important;
}
.syntaxhighlighter.collapsed .toolbar span a {
padding: 0 !important;
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar span a.expandSource {
display: inline !important;
}
.syntaxhighlighter .toolbar {
position: absolute !important;
right: 1px !important;
top: 1px !important;
width: 11px !important;
height: 11px !important;
font-size: 10px !important;
z-index: 10 !important;
}
.syntaxhighlighter .toolbar span.title {
display: inline !important;
}
.syntaxhighlighter .toolbar a {
display: block !important;
text-align: center !important;
text-decoration: none !important;
padding-top: 1px !important;
}
.syntaxhighlighter .toolbar a.expandSource {
display: none !important;
}
.syntaxhighlighter.ie {
font-size: .9em !important;
padding: 1px 0 1px 0 !important;
}
.syntaxhighlighter.ie .toolbar {
line-height: 8px !important;
}
.syntaxhighlighter.ie .toolbar a {
padding-top: 0px !important;
}
.syntaxhighlighter.printing .line.alt1 .content,
.syntaxhighlighter.printing .line.alt2 .content,
.syntaxhighlighter.printing .line.highlighted .number,
.syntaxhighlighter.printing .line.highlighted.alt1 .content,
.syntaxhighlighter.printing .line.highlighted.alt2 .content {
background: none !important;
}
.syntaxhighlighter.printing .line .number {
color: #bbbbbb !important;
}
.syntaxhighlighter.printing .line .content {
color: black !important;
}
.syntaxhighlighter.printing .toolbar {
display: none !important;
}
.syntaxhighlighter.printing a {
text-decoration: none !important;
}
.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
color: black !important;
}
.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
color: #008200 !important;
}
.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
color: blue !important;
}
.syntaxhighlighter.printing .keyword {
color: #006699 !important;
font-weight: bold !important;
}
.syntaxhighlighter.printing .preprocessor {
color: gray !important;
}
.syntaxhighlighter.printing .variable {
color: #aa7700 !important;
}
.syntaxhighlighter.printing .value {
color: #009900 !important;
}
.syntaxhighlighter.printing .functions {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .constants {
color: #0066cc !important;
}
.syntaxhighlighter.printing .script {
font-weight: bold !important;
}
.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
color: gray !important;
}
.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
color: red !important;
}
.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
color: black !important;
}
.syntaxhighlighter {
background-color: white !important;
}
.syntaxhighlighter .line.alt1 {
background-color: white !important;
}
.syntaxhighlighter .line.alt2 {
background-color: white !important;
}
.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
background-color: #e0e0e0 !important;
}
.syntaxhighlighter .line.highlighted.number {
color: black !important;
}
.syntaxhighlighter table caption {
color: black !important;
}
.syntaxhighlighter .gutter {
color: #afafaf !important;
}
.syntaxhighlighter .gutter .line {
border-right: 3px solid #6ce26c !important;
}
.syntaxhighlighter .gutter .line.highlighted {
background-color: #6ce26c !important;
color: white !important;
}
.syntaxhighlighter.printing .line .content {
border: none !important;
}
.syntaxhighlighter.collapsed {
overflow: visible !important;
}
.syntaxhighlighter.collapsed .toolbar {
color: blue !important;
background: white !important;
border: 1px solid #6ce26c !important;
}
.syntaxhighlighter.collapsed .toolbar a {
color: blue !important;
}
.syntaxhighlighter.collapsed .toolbar a:hover {
color: red !important;
}
.syntaxhighlighter .toolbar {
color: white !important;
background: #6ce26c !important;
border: none !important;
}
.syntaxhighlighter .toolbar a {
color: white !important;
}
.syntaxhighlighter .toolbar a:hover {
color: black !important;
}
.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
color: black !important;
}
.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
color: #008200 !important;
}
.syntaxhighlighter .string, .syntaxhighlighter .string a {
color: blue !important;
}
.syntaxhighlighter .keyword {
color: #006699 !important;
}
.syntaxhighlighter .preprocessor {
color: gray !important;
}
.syntaxhighlighter .variable {
color: #aa7700 !important;
}
.syntaxhighlighter .value {
color: #009900 !important;
}
.syntaxhighlighter .functions {
color: #ff1493 !important;
}
.syntaxhighlighter .constants {
color: #0066cc !important;
}
.syntaxhighlighter .script {
font-weight: bold !important;
color: #006699 !important;
background-color: none !important;
}
.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
color: gray !important;
}
.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
color: red !important;
}
.syntaxhighlighter .keyword {
font-weight: bold !important;
}

View File

@ -1,117 +0,0 @@
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter {
background-color: white !important;
}
.syntaxhighlighter .line.alt1 {
background-color: white !important;
}
.syntaxhighlighter .line.alt2 {
background-color: white !important;
}
.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
background-color: #e0e0e0 !important;
}
.syntaxhighlighter .line.highlighted.number {
color: black !important;
}
.syntaxhighlighter table caption {
color: black !important;
}
.syntaxhighlighter .gutter {
color: #afafaf !important;
}
.syntaxhighlighter .gutter .line {
border-right: 3px solid #6ce26c !important;
}
.syntaxhighlighter .gutter .line.highlighted {
background-color: #6ce26c !important;
color: white !important;
}
.syntaxhighlighter.printing .line .content {
border: none !important;
}
.syntaxhighlighter.collapsed {
overflow: visible !important;
}
.syntaxhighlighter.collapsed .toolbar {
color: blue !important;
background: white !important;
border: 1px solid #6ce26c !important;
}
.syntaxhighlighter.collapsed .toolbar a {
color: blue !important;
}
.syntaxhighlighter.collapsed .toolbar a:hover {
color: red !important;
}
.syntaxhighlighter .toolbar {
color: white !important;
background: #6ce26c !important;
border: none !important;
}
.syntaxhighlighter .toolbar a {
color: white !important;
}
.syntaxhighlighter .toolbar a:hover {
color: black !important;
}
.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
color: black !important;
}
.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
color: #008200 !important;
}
.syntaxhighlighter .string, .syntaxhighlighter .string a {
color: blue !important;
}
.syntaxhighlighter .keyword {
color: #006699 !important;
}
.syntaxhighlighter .preprocessor {
color: gray !important;
}
.syntaxhighlighter .variable {
color: #aa7700 !important;
}
.syntaxhighlighter .value {
color: #009900 !important;
}
.syntaxhighlighter .functions {
color: #ff1493 !important;
}
.syntaxhighlighter .constants {
color: #0066cc !important;
}
.syntaxhighlighter .script {
font-weight: bold !important;
color: #006699 !important;
background-color: none !important;
}
.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
color: gray !important;
}
.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
color: red !important;
}
.syntaxhighlighter .keyword {
font-weight: bold !important;
}

View File

@ -0,0 +1,21 @@
package ca.uhn.fhir.context;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.resource.ValueSet;
public class FhirContextTest {
@Test
public void testIncrementalScan() {
FhirContext ctx = new FhirContext();
ctx.getResourceDefinition(ValueSet.class);
ctx.getResourceDefinition(Patient.class);
}
}

View File

@ -2,6 +2,8 @@ package ca.uhn.fhir.model.primitive;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
import org.junit.BeforeClass;
import org.junit.Test;
@ -29,6 +31,15 @@ public class IdDtTest {
}
@Test
public void testBigDecimalIds() {
IdDt id = new IdDt(new BigDecimal("123"));
assertEquals(id.asBigDecimal(), new BigDecimal("123"));
assertEquals(id.getIdPartAsBigDecimal(), new BigDecimal("123"));
}
@Test
public void testParseValueAbsoluteWithVersion() {
Patient patient = new Patient();

View File

@ -25,10 +25,12 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.internal.matchers.Not;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
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.TagList;
import ca.uhn.fhir.model.api.annotation.Child;
@ -84,6 +86,28 @@ public class JsonParserTest {
}
@Test
public void testParseEmptyNarrative() throws ConfigurationException, DataFormatException, IOException {
//@formatter:off
String text = "{\n" +
" \"resourceType\" : \"Patient\",\n" +
" \"extension\" : [\n" +
" {\n" +
" \"url\" : \"http://clairol.org/colour\",\n" +
" \"valueCode\" : \"B\"\n" +
" }\n" +
" ],\n" +
" \"text\" : {\n" +
" \"div\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\"\n" +
" }" +
"}";
//@formatter:on
IResource res = ourCtx.newJsonParser().parseResource(text);
}
@Test
public void testNestedContainedResources() {

View File

@ -79,7 +79,6 @@ public class XmlParserTest {
}
@Test
public void testNestedContainedResources() {

View File

@ -34,6 +34,7 @@ import ca.uhn.fhir.model.dstu.resource.Encounter;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
@ -72,12 +73,15 @@ public class GenericClientTest {
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[] {new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
IGenericClient client = myCtx.newRestfulGenericClient("http://example.com/fhir");
client.create(p1);
MethodOutcome outcome = client.create(p1);
assertEquals("44",outcome.getId().getIdPart());
assertEquals("22",outcome.getId().getVersionIdPart());
assertEquals("http://example.com/fhir/Patient", capt.getValue().getURI().toString());
assertEquals("POST", capt.getValue().getMethod());

View File

@ -0,0 +1,196 @@
package ca.uhn.fhir.rest.method;
import static org.junit.Assert.*;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.TagList;
public class BaseOutcomeReturningMethodBindingTest {
@Test
public void testParseTagHeader() {
String headerString = "http://britsystems.com/fhir/tag/4567; scheme=\"http://britsystems.com/fhir\"; label=\"Tag-4567\",http://client/scheme/tag/123; scheme=\"http://client/scheme\"; label=\"tag 123\",http://client/scheme/tag/456; scheme=\"http://client/scheme\"; label=\"tag 456\",http://fhir.healthintersections.com.au/open/Patient/1; scheme=\"http://hl7.org/fhir/tag\"; label=\"GET <host>/<resourceType>/<id>\",http://hl7.fhir/example; scheme=\"http://hl7.org/fhir/tag\"; label=\"FHIR example\",http://hl7.org/fhir/sid/us-ssn; scheme=\"http://hl7.org/fhir/tag\"; label=\"POST <host>/<resourceType>\",http://hl7.org/fhir/tools/tag/test; scheme=\"http://hl7.org/fhir/tag\"; label=\"Test Tag\",http://hl7.org/implement/standards/fhir/v3/ActCode/InformationSensitivityPolicy#GDIS; scheme=\"http://hl7.org/fhir/tag\"; label=\"GDIS\",http://hl7.org/implement/standards/fhir/v3/Confidentiality#N; scheme=\"http://hl7.org/fhir/tag\"; label=\"N (Normal)\",http://hl7.org/implement/standards/fhir/v3/Confidentiality#R; scheme=\"http://hl7.org/fhir/tag\"; label=\"restricted\",http://nu.nl/testname; scheme=\"http://hl7.org/fhir/tag\"; label=\"TestCreateEditDelete\",http://readtag.nu.nl; scheme=\"http://hl7.org/fhir/tag\"; label=\"readTagTest\",http://spark.furore.com/fhir; scheme=\"http://hl7.org/fhir/tag\"; label=\"GET <host>/<resourceType>/<id>\",http://www.healthintersections.com.au/fhir/tags/invalid; scheme=\"http://hl7.org/fhir/tag\"; label=\"Non-conformant Resource\",urn:happytag; scheme=\"http://hl7.org/fhir/tag\"; label=\"This is a happy resource\",condition; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile condition\",device; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile device\",http://fhir.healthintersections.com.au/open/Profile/condition; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile condition\",http://fhir.healthintersections.com.au/open/Profile/device; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"Profile device\",http://hl7.org/fhir/v3/ActCode#CEL; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Celebrity / VIP\",http://hl7.org/fhir/v3/ActCode#DEMO; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Contact/Employment Confidential\",http://hl7.org/fhir/v3/ActCode#DIA; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Diagnosis is/would be Confidential\",http://hl7.org/fhir/v3/ActCode#EMP; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Employee / Staff member\",http://hl7.org/fhir/v3/ActCode#ORCON; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Author only\",http://hl7.org/fhir/v3/ActCode#TABOO; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Patient/Carer Only\",http://hl7.org/fhir/v3/Confidentiality#L; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Low\",http://hl7.org/fhir/v3/Confidentiality#M; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Moderate\",http://hl7.org/fhir/v3/Confidentiality#N; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Normal\",http://hl7.org/fhir/v3/Confidentiality#R; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Restricted\",http://hl7.org/fhir/v3/Confidentiality#U; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = none\",http://hl7.org/fhir/v3/Confidentiality#V; scheme=\"http://hl7.org/fhir/tag/security\"; label=\"Confidentiality = Very Restricted\",http://term.com; scheme=\"http://scheme.com\"; label=\"Some good ole term\"";
TagList parsedFromHeader = new TagList();
BaseOutcomeReturningMethodBinding.parseTagValue(parsedFromHeader, headerString);
//@formatter:off
String resourceString = "{\n" +
" \"resourceType\" : \"TagList\",\n" +
" \"category\" : [\n" +
" {\n" +
" \"scheme\" : \"http://britsystems.com/fhir\",\n" +
" \"term\" : \"http://britsystems.com/fhir/tag/4567\",\n" +
" \"label\" : \"Tag-4567\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://client/scheme\",\n" +
" \"term\" : \"http://client/scheme/tag/123\",\n" +
" \"label\" : \"tag 123\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://client/scheme\",\n" +
" \"term\" : \"http://client/scheme/tag/456\",\n" +
" \"label\" : \"tag 456\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://fhir.healthintersections.com.au/open/Patient/1\",\n" +
" \"label\" : \"GET <host>/<resourceType>/<id>\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://hl7.fhir/example\",\n" +
" \"label\" : \"FHIR example\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://hl7.org/fhir/sid/us-ssn\",\n" +
" \"label\" : \"POST <host>/<resourceType>\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://hl7.org/fhir/tools/tag/test\",\n" +
" \"label\" : \"Test Tag\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://hl7.org/implement/standards/fhir/v3/ActCode/InformationSensitivityPolicy#GDIS\",\n" +
" \"label\" : \"GDIS\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://hl7.org/implement/standards/fhir/v3/Confidentiality#N\",\n" +
" \"label\" : \"N (Normal)\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://hl7.org/implement/standards/fhir/v3/Confidentiality#R\",\n" +
" \"label\" : \"restricted\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://nu.nl/testname\",\n" +
" \"label\" : \"TestCreateEditDelete\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://readtag.nu.nl\",\n" +
" \"label\" : \"readTagTest\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://spark.furore.com/fhir\",\n" +
" \"label\" : \"GET <host>/<resourceType>/<id>\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"http://www.healthintersections.com.au/fhir/tags/invalid\",\n" +
" \"label\" : \"Non-conformant Resource\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag\",\n" +
" \"term\" : \"urn:happytag\",\n" +
" \"label\" : \"This is a happy resource\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/profile\",\n" +
" \"term\" : \"condition\",\n" +
" \"label\" : \"Profile condition\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/profile\",\n" +
" \"term\" : \"device\",\n" +
" \"label\" : \"Profile device\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/profile\",\n" +
" \"term\" : \"http://fhir.healthintersections.com.au/open/Profile/condition\",\n" +
" \"label\" : \"Profile condition\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/profile\",\n" +
" \"term\" : \"http://fhir.healthintersections.com.au/open/Profile/device\",\n" +
" \"label\" : \"Profile device\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/ActCode#CEL\",\n" +
" \"label\" : \"Celebrity / VIP\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/ActCode#DEMO\",\n" +
" \"label\" : \"Contact/Employment Confidential\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/ActCode#DIA\",\n" +
" \"label\" : \"Diagnosis is/would be Confidential\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/ActCode#EMP\",\n" +
" \"label\" : \"Employee / Staff member\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/ActCode#ORCON\",\n" +
" \"label\" : \"Author only\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/ActCode#TABOO\",\n" +
" \"label\" : \"Patient/Carer Only\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/Confidentiality#L\",\n" +
" \"label\" : \"Confidentiality = Low\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/Confidentiality#M\",\n" +
" \"label\" : \"Confidentiality = Moderate\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/Confidentiality#N\",\n" +
" \"label\" : \"Confidentiality = Normal\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/Confidentiality#R\",\n" +
" \"label\" : \"Confidentiality = Restricted\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/Confidentiality#U\",\n" +
" \"label\" : \"Confidentiality = none\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://hl7.org/fhir/tag/security\",\n" +
" \"term\" : \"http://hl7.org/fhir/v3/Confidentiality#V\",\n" +
" \"label\" : \"Confidentiality = Very Restricted\"\n" +
" },\n" +
" {\n" +
" \"scheme\" : \"http://scheme.com\",\n" +
" \"term\" : \"http://term.com\",\n" +
" \"label\" : \"Some good ole term\"\n" +
" }\n" +
" ]\n" +
"}";
//@formatter:on
TagList parsedFromResource = new FhirContext().newJsonParser().parseTagList(resourceString);
assertEquals(parsedFromHeader.size(), parsedFromResource.size());
for (int i = 0; i < parsedFromHeader.size(); i++) {
assertEquals(parsedFromHeader.get(i), parsedFromResource.get(i));
}
}
}

View File

@ -0,0 +1,152 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.gzip.GzipHandler;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.testutil.RandomServerPortProvider;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class CompressionTest {
private static CloseableHttpClient ourClient;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CompressionTest.class);
private static int ourPort;
private static Server ourServer;
private static FhirContext ourCtx;
public static String decompress(byte[] theResource) {
GZIPInputStream is;
try {
is = new GZIPInputStream(new ByteArrayInputStream(theResource));
return IOUtils.toString(is, "UTF-8");
} catch (IOException e) {
throw new DataFormatException("Failed to decompress contents", e);
}
}
@Test
public void testRead() throws Exception {
{
/*
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader(Constants.HEADER_ACCEPT_ENCODING, "gzip");
HttpResponse status = ourClient.execute(httpGet);
Header ce = status.getFirstHeader(Constants.HEADER_CONTENT_ENCODING);
*/
URLConnection c = new URL("http://localhost:" + ourPort + "/Patient/1").openConnection();
c.addRequestProperty(Constants.HEADER_ACCEPT_ENCODING, "gzip");
String enc = c.getContentEncoding();
assertEquals("gzip", enc);
byte[] responseContentBytes = IOUtils.toByteArray(c.getInputStream());
String responseContent = decompress(responseContentBytes);
IdentifierDt dt = ourCtx.newXmlParser().parseResource(Patient.class,responseContent).getIdentifierFirstRep();
assertEquals("1", dt.getSystem().getValueAsString());
assertEquals(null, dt.getValue().getValueAsString());
}
}
@Test
public void testVRead() throws Exception {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/_history/2");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
IdentifierDt dt = ourCtx.newXmlParser().parseResource(Patient.class,responseContent).getIdentifierFirstRep();
assertEquals("1", dt.getSystem().getValueAsString());
assertEquals("2", dt.getValue().getValueAsString());
}
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = RandomServerPortProvider.findFreePort();
ourServer = new Server(ourPort);
DummyProvider patientProvider = new DummyProvider();
ServletHandler proxyHandler = new ServletHandler();
RestfulServer servlet = new RestfulServer();
ourCtx = servlet.getFhirContext();
servlet.setResourceProviders(patientProvider);
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
// GzipHandler gh = new GzipHandler();
// gh.setHandler(proxyHandler);
// gh.setMimeTypes(Constants.CT_ATOM_XML+','+Constants.CT_FHIR_JSON+','+Constants.CT_FHIR_XML);
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class DummyProvider implements IResourceProvider {
@Read(version = true)
public Patient findPatient(@IdParam IdDt theId) {
Patient patient = new Patient();
patient.addIdentifier(theId.getIdPart(), theId.getVersionIdPart());
patient.setId("Patient/1/_history/1");
return patient;
}
@Override
public Class<? extends IResource> getResourceType() {
return Patient.class;
}
}
}

View File

@ -0,0 +1,114 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.hamcrest.core.StringContains;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.testutil.RandomServerPortProvider;
/**
* Created by dsotnikov on 2/25/2014.
*/
public class ExceptionTest {
private static CloseableHttpClient ourClient;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExceptionTest.class);
private static int ourPort;
private static Server ourServer;
private static RestfulServer servlet;
@Test
public void testSearchNormalMatch() throws Exception {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?throwInternalError=aaa");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
ourLog.info(responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
OperationOutcome oo = (OperationOutcome) servlet.getFhirContext().newXmlParser().parseResource(responseContent);
assertThat(oo.getIssueFirstRep().getDetails().getValue(), StringContains.containsString("InternalErrorException: Exception Text"));
}
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?throwInternalError=aaa&_format=json");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
ourLog.info(responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
OperationOutcome oo = (OperationOutcome) servlet.getFhirContext().newJsonParser().parseResource(responseContent);
assertThat(oo.getIssueFirstRep().getDetails().getValue(), StringContains.containsString("InternalErrorException: Exception Text"));
}
}
@AfterClass
public static void afterClass() throws Exception {
ourServer.stop();
}
@BeforeClass
public static void beforeClass() throws Exception {
ourPort = RandomServerPortProvider.findFreePort();
ourServer = new Server(ourPort);
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
ServletHandler proxyHandler = new ServletHandler();
servlet = new RestfulServer();
servlet.setResourceProviders(patientProvider);
ServletHolder servletHolder = new ServletHolder(servlet);
proxyHandler.addServletWithMapping(servletHolder, "/*");
ourServer.setHandler(proxyHandler);
ourServer.start();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
ourClient = builder.build();
}
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class DummyPatientResourceProvider implements IResourceProvider {
@Search
public List<Patient> findPatient(@RequiredParam(name = "throwInternalError") StringParam theParam) {
throw new InternalErrorException("Exception Text");
}
@Override
public Class<? extends IResource> getResourceType() {
return Patient.class;
}
}
}

View File

@ -47,7 +47,8 @@ public class IncludeTest {
public void testNoIncludes() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());
@ -61,7 +62,8 @@ public class IncludeTest {
public void testOneInclude() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_include=foo");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());
@ -76,7 +78,8 @@ public class IncludeTest {
public void testTwoInclude() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_include=foo&_include=bar");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());

View File

@ -52,29 +52,55 @@ public class PagingTest {
String link;
String base = "http://localhost:" + ourPort;
{
HttpGet httpGet = new HttpGet(base+ "/Patient?");
HttpGet httpGet = new HttpGet(base+ "/Patient?_format=xml&_pretty=true");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
assertEquals(5, bundle.getEntries().size());
assertEquals("0", bundle.getEntries().get(0).getId().getIdPart());
assertEquals("4", bundle.getEntries().get(4).getId().getIdPart());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=5&" + Constants.PARAM_COUNT + "=5", bundle.getLinkNext().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=5&" + Constants.PARAM_COUNT + "=5&_format=xml&_pretty=true", bundle.getLinkNext().getValue());
assertNull(bundle.getLinkPrevious().getValue());
link=bundle.getLinkNext().getValue();
}
{
HttpGet httpGet = new HttpGet(link);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
assertEquals(5, bundle.getEntries().size());
assertEquals("5", bundle.getEntries().get(0).getId().getIdPart());
assertEquals("9", bundle.getEntries().get(4).getId().getIdPart());
assertNull(bundle.getLinkNext().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=5", bundle.getLinkPrevious().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=5&_format=xml&_pretty=true", bundle.getLinkPrevious().getValue());
}
}
@Test
public void testSearchInexactOffset() throws Exception {
when(myPagingProvider.getDefaultPageSize()).thenReturn(5);
when(myPagingProvider.getMaximumPageSize()).thenReturn(9);
when(myPagingProvider.storeResultList(any(IBundleProvider.class))).thenReturn("ABCD");
when(myPagingProvider.retrieveResultList(eq("ABCD"))).thenReturn(ourBundleProvider);
String base = "http://localhost:" + ourPort;
{
HttpGet httpGet = new HttpGet(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=8&" + Constants.PARAM_COUNT + "=5&_format=xml&_pretty=true");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
assertEquals(2, bundle.getEntries().size());
assertEquals("8", bundle.getEntries().get(0).getId().getIdPart());
assertEquals("9", bundle.getEntries().get(1).getId().getIdPart());
assertNull(bundle.getLinkNext().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=3&" + Constants.PARAM_COUNT + "=5&_format=xml&_pretty=true", bundle.getLinkPrevious().getValue());
}
}
@ -91,28 +117,30 @@ public class PagingTest {
{
HttpGet httpGet = new HttpGet(base+ "/Patient?_count=2");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
assertEquals(2, bundle.getEntries().size());
assertEquals("0", bundle.getEntries().get(0).getId().getIdPart());
assertEquals("1", bundle.getEntries().get(1).getId().getIdPart());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2", bundle.getLinkNext().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkNext().getValue());
assertNull(bundle.getLinkPrevious().getValue());
link=bundle.getLinkNext().getValue();
}
{
HttpGet httpGet = new HttpGet(link);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourContext.newXmlParser().parseBundle(responseContent);
assertEquals(2, bundle.getEntries().size());
assertEquals("2", bundle.getEntries().get(0).getId().getIdPart());
assertEquals("3", bundle.getEntries().get(1).getId().getIdPart());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=4&" + Constants.PARAM_COUNT + "=2", bundle.getLinkNext().getValue());
assertEquals(base + '/'+'?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2", bundle.getLinkSelf().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=2", bundle.getLinkPrevious().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=4&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkNext().getValue());
assertEquals(base + '/'+'?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=2&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkSelf().getValue());
assertEquals(base + '?'+Constants.PARAM_PAGINGACTION + "=ABCD&" + Constants.PARAM_PAGINGOFFSET + "=0&" + Constants.PARAM_COUNT + "=2&_format=xml", bundle.getLinkPrevious().getValue());
}
}

View File

@ -69,6 +69,7 @@ public class PlainProviderTest {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(connectionManager);
myClient = builder.build();
@ -90,6 +91,7 @@ public class PlainProviderTest {
HttpResponse status = myClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -102,6 +104,8 @@ public class PlainProviderTest {
assertEquals(uri, bundle.getLinkSelf().getValue());
assertEquals(baseUri, bundle.getLinkBase().getValue());
httpGet.releaseConnection();
}
@Test
@ -114,6 +118,7 @@ public class PlainProviderTest {
HttpResponse status = myClient.execute(new HttpGet(baseUri + "/_history?_since=2012-01-02T00%3A01%3A02&_count=12"));
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = myCtx.newXmlParser().parseBundle(responseContent);
@ -124,14 +129,16 @@ public class PlainProviderTest {
status = myClient.execute(new HttpGet(baseUri + "/_history?&_count=12"));
responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
bundle = myCtx.newXmlParser().parseBundle(responseContent);
assertEquals(3, bundle.getEntries().size());
assertNull(provider.myLastSince.getValueAsString());
assertThat(provider.myLastCount.getValueAsString(), IsEqual.equalTo("12"));
status =myClient.execute(new HttpGet(baseUri + "/_history?_since=2012-01-02T00%3A01%3A02"));
responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
bundle = myCtx.newXmlParser().parseBundle(responseContent);
assertEquals(3, bundle.getEntries().size());
@ -140,6 +147,7 @@ public class PlainProviderTest {
status =myClient.execute(new HttpGet(baseUri + "/_history"));
responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
bundle = myCtx.newXmlParser().parseBundle(responseContent);
assertEquals(3, bundle.getEntries().size());

View File

@ -48,7 +48,9 @@ public class ReferenceParameterTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+"=123");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
List<BundleEntry> entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
assertEquals(1, entries.size());
@ -64,7 +66,8 @@ public class ReferenceParameterTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+":Organization=123");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
List<BundleEntry> entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
assertEquals(1, entries.size());
@ -79,7 +82,8 @@ public class ReferenceParameterTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+":Organization.name=123");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
List<BundleEntry> entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
assertEquals(1, entries.size());
@ -95,7 +99,8 @@ public class ReferenceParameterTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?" + Patient.SP_PROVIDER+".name=123");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
List<BundleEntry> entries = new FhirContext().newXmlParser().parseBundle(responseContent).getEntries();
assertEquals(1, entries.size());

View File

@ -103,7 +103,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/DiagnosticReport?throw404=true");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(404, status.getStatusLine().getStatusCode());
@ -123,10 +124,11 @@ public class ResfulServerMethodTest {
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("Location").getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("location").getValue());
}
@ -143,11 +145,12 @@ public class ResfulServerMethodTest {
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(201, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("Location").getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("location").getValue());
}
@ -162,7 +165,8 @@ public class ResfulServerMethodTest {
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
@ -183,7 +187,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?dateRange=%3E%3D2011-01-01&dateRange=%3C%3D2021-01-01");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -200,7 +205,8 @@ public class ResfulServerMethodTest {
HttpDelete httpGet = new HttpDelete("http://localhost:" + ourPort + "/Patient/1234");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -230,7 +236,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include3");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = ourCtx.newXmlParser().parseBundle(responseContent);
BundleEntry entry0 = bundle.getEntries().get(0);
@ -239,7 +246,8 @@ public class ResfulServerMethodTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include3&_format=json");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
ourLog.info(responseContent);
bundle = ourCtx.newJsonParser().parseBundle(responseContent);
@ -260,7 +268,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=json");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -284,7 +293,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=xml");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -304,7 +314,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -318,7 +329,8 @@ public class ResfulServerMethodTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.debug("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -332,7 +344,8 @@ public class ResfulServerMethodTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/9999999");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.debug("Response was:\n{}", responseContent);
assertEquals(404, status.getStatusLine().getStatusCode());
@ -350,7 +363,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/_history/999");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -366,7 +380,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
// ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -401,7 +416,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/999/_history");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
@ -410,7 +426,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/998/_history");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(500, status.getStatusLine().getStatusCode());
@ -437,7 +454,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/222/_history");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -486,7 +504,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_history");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -537,7 +556,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/AdverseReaction/223");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(Constants.STATUS_HTTP_400_BAD_REQUEST, status.getStatusLine().getStatusCode());
@ -550,7 +570,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/AdverseReaction");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -561,7 +582,8 @@ public class ResfulServerMethodTest {
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/AdverseReaction/_search");
status = ourClient.execute(httpPost);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -577,7 +599,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Profile?");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
// ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -594,7 +617,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?dob=2011-01-02");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -613,7 +637,8 @@ public class ResfulServerMethodTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?dob=%3E%3D2011-01-02");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -633,7 +658,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_search?dob=2011-01-02");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -650,7 +676,8 @@ public class ResfulServerMethodTest {
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search?dob=2011-01-02");
status = ourClient.execute(httpPost);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -670,7 +697,8 @@ public class ResfulServerMethodTest {
httpPost.setEntity(new UrlEncodedFormEntity(urlParameters));
status = ourClient.execute(httpPost);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -690,7 +718,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?ids=urn:aaa%7Caaa,urn:bbb%7Cbbb");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -709,7 +738,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=urn:hapitest:mrns%7C00001");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -726,7 +756,8 @@ public class ResfulServerMethodTest {
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient/_search?identifier=urn:hapitest:mrns%7C00001");
status = ourClient.execute(httpPost);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -743,7 +774,8 @@ public class ResfulServerMethodTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_search?identifier=urn:hapitest:mrns%7C00001");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -761,7 +793,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/?_query=someQueryNoParams");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -784,7 +817,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/?_query=someQueryOneParam&param1=AAAA");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -804,7 +838,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/?quantityParam=%3E%3D123%7Cfoo%7Cbar");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -822,7 +857,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include3");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -841,7 +877,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1&_include=include2&_include=include4");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(400, status.getStatusLine().getStatusCode());
@ -853,7 +890,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?withIncludes=include1");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
// Make sure there is no crash
@ -866,7 +904,8 @@ public class ResfulServerMethodTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name1=AAA");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -885,7 +924,8 @@ public class ResfulServerMethodTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name1=AAA&name2=BBB");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -910,14 +950,15 @@ public class ResfulServerMethodTest {
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
OperationOutcome oo = new FhirContext().newXmlParser().parseResource(OperationOutcome.class, responseContent);
assertEquals("OODETAILS", oo.getIssueFirstRep().getDetails().getValue());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("Location").getValue());
assertEquals("http://localhost:" + ourPort + "/Patient/001/_history/002", status.getFirstHeader("location").getValue());
}
@ -933,7 +974,7 @@ public class ResfulServerMethodTest {
HttpResponse status = ourClient.execute(httpPost);
assertEquals(204, status.getStatusLine().getStatusCode());
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("Location").getValue());
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("location").getValue());
}
@ -1087,7 +1128,8 @@ public class ResfulServerMethodTest {
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertThat(responseContent, not(containsString("\n ")));
@ -1105,7 +1147,8 @@ public class ResfulServerMethodTest {
status = ourClient.execute(httpPost);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(422, status.getStatusLine().getStatusCode());
@ -1142,7 +1185,8 @@ public class ResfulServerMethodTest {
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertThat(responseContent, containsString("\n "));
}
@ -1153,7 +1197,8 @@ public class ResfulServerMethodTest {
HttpDelete httpGet = new HttpDelete("http://localhost:" + ourPort + "/Patient/1234?_pretty=true");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());

View File

@ -5,20 +5,29 @@ import static org.junit.Assert.*;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.PathSpecification;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResourceSearchParam;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.annotation.IncludeParam;
import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.SearchMethodBinding;
import ca.uhn.fhir.rest.param.CodingListParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.SearchParameter;
import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
@ -90,6 +99,31 @@ public class ServerConformanceProviderTest {
assertThat(conf, containsString("<type value=\"token\"/>"));
}
@Test
public void testProviderWithRequiredAndOptional() throws Exception {
RestfulServer rs = new RestfulServer();
rs.setProviders(new ProviderWithRequiredAndOptional());
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
rs.setServerConformanceProvider(sc);
rs.init(null);
Conformance conformance = sc.getServerConformance();
String conf = new FhirContext().newJsonParser().setPrettyPrint(true).encodeResourceToString(conformance);
ourLog.info(conf);
RestResource res = conformance.getRestFirstRep().getResourceFirstRep();
assertEquals("DiagnosticReport", res.getType().getValueAsString());
RestResourceSearchParam p0 = res.getSearchParam().get(0);
assertEquals("subject", p0.getName().getValue());
assertEquals(1,res.getSearchInclude().size());
assertEquals("DiagnosticReport.result", res.getSearchIncludeFirstRep().getValue());
}
/**
* Created by dsotnikov on 2/25/2014.
@ -123,5 +157,22 @@ public class ServerConformanceProviderTest {
}
}
public static class ProviderWithRequiredAndOptional {
@Search
public List<DiagnosticReport> findDiagnosticReportsByPatient (
@RequiredParam(name=DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId,
@OptionalParam(name=DiagnosticReport.SP_NAME) CodingListParam theNames,
@OptionalParam(name=DiagnosticReport.SP_DATE) DateRangeParam theDateRange,
@IncludeParam(allow= {"DiagnosticReport.result"}) Set<Include> theIncludes
) throws Exception {
return null;
}
}
}

View File

@ -52,7 +52,8 @@ public class ServerFeaturesTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
/*
@ -61,7 +62,8 @@ public class ServerFeaturesTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=false");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
/*
@ -70,7 +72,8 @@ public class ServerFeaturesTest {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_pretty=true");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, IsNot.not(StringContains.containsString("<identifier><use")));
}
@ -80,19 +83,22 @@ public class ServerFeaturesTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_FHIR_XML);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_ATOM_XML);
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_FHIR_JSON);
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("\"identifier\":"));
}
@ -102,19 +108,22 @@ public class ServerFeaturesTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", "text/plain, " + Constants.CT_FHIR_XML);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", "text/plain, " + Constants.CT_ATOM_XML);
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", "text/plain, " + Constants.CT_FHIR_JSON);
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("\"identifier\":"));
}
@ -125,13 +134,15 @@ public class ServerFeaturesTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_XML);
CloseableHttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier><use"));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_JSON);
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("\"identifier\":"));
}
@ -142,13 +153,15 @@ public class ServerFeaturesTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_FHIR_XML+ "; pretty=true");
CloseableHttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("<identifier>\n "));
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
httpGet.addHeader("Accept", Constants.CT_FHIR_JSON+ "; pretty=true");
status = ourClient.execute(httpGet);
responseContent = IOUtils.toString(status.getEntity().getContent());
responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertThat(responseContent, StringContains.containsString("\",\n"));
}
@ -160,7 +173,8 @@ public class ServerFeaturesTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/?_query=findPatientsWithNoIdSpecified");
httpGet.addHeader("Accept", Constants.CT_FHIR_XML+ "; pretty=true");
CloseableHttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(500, status.getStatusLine().getStatusCode());
assertThat(responseContent, StringContains.containsString("ID"));

View File

@ -44,7 +44,8 @@ public class SortTest {
public void testNoSort() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());
@ -59,7 +60,8 @@ public class SortTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort=given");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());
@ -72,7 +74,8 @@ public class SortTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort:asc=given");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());
@ -85,7 +88,8 @@ public class SortTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort:desc=given");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());
@ -103,7 +107,8 @@ public class SortTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?name=Hello&_sort=given&_sort=family&_sort=name");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
Bundle bundle = new FhirContext().newXmlParser().parseBundle(responseContent);
assertEquals(1, bundle.size());

View File

@ -37,26 +37,43 @@ public class StringParameterTest {
private static int ourPort;
private static Server ourServer;
@Test
public void testSearchWithFormatAndPretty() throws Exception {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?str=aaa&_format=xml&_pretty=true");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(1, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
}
@Test
public void testSearchNormalMatch() throws Exception {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?str=aaa");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(1, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?str=AAA");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(1, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?str=BBB");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(0, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
@ -67,14 +84,16 @@ public class StringParameterTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?plain=aaa");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(1, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?plain=BBB");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(0, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
@ -85,21 +104,24 @@ public class StringParameterTest {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?str:exact=aaa");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(1, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?str:exact=AAA");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(0, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?str:exact=BBB");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
assertEquals(0, new FhirContext().newXmlParser().parseBundle(responseContent).getEntries().size());
}

View File

@ -66,7 +66,8 @@ public class TagsServerTest {
httpPost.setEntity(new StringEntity(ourCtx.newJsonParser().encodeTagListToString(tagList), ContentType.create(EncodingEnum.JSON.getResourceContentType(), "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -84,7 +85,8 @@ public class TagsServerTest {
httpPost.setEntity(new StringEntity(ourCtx.newJsonParser().encodeTagListToString(tagList), ContentType.create(EncodingEnum.JSON.getResourceContentType(), "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -110,7 +112,8 @@ public class TagsServerTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/_tags");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -124,7 +127,8 @@ public class TagsServerTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_tags");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -141,7 +145,8 @@ public class TagsServerTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/111/_tags");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -158,7 +163,8 @@ public class TagsServerTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/111/_history/222/_tags");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -175,7 +181,8 @@ public class TagsServerTest {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/111/_history/222/_tags");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -196,7 +203,8 @@ public class TagsServerTest {
httpPost.setEntity(new StringEntity(ourCtx.newJsonParser().encodeTagListToString(tagList), ContentType.create(EncodingEnum.JSON.getResourceContentType(), "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -214,7 +222,8 @@ public class TagsServerTest {
httpPost.setEntity(new StringEntity(ourCtx.newJsonParser().encodeTagListToString(tagList), ContentType.create(EncodingEnum.JSON.getResourceContentType(), "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());

View File

@ -1,263 +0,0 @@
package ca.uhn.fhir.rest.server;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.tester.RestfulServerTesterServlet;
import ca.uhn.fhir.testutil.RandomServerPortProvider;
public class TesterTest {
private int myPort;
private Server myServer;
private FhirContext myCtx;
private RestfulServer myRestfulServer;
@Before
public void before() throws Exception {
myPort = RandomServerPortProvider.findFreePort();
myPort = 8888;
myServer = new Server(myPort);
myCtx = new FhirContext();
myCtx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
myRestfulServer = new RestfulServer(myCtx);
ServletContextHandler proxyHandler = new ServletContextHandler();
proxyHandler.setContextPath("/");
RestfulServerTesterServlet testerServlet = new RestfulServerTesterServlet();
testerServlet.setServerBase("http://localhost:" + myPort + "/fhir/context");
// testerServlet.setServerBase("http://fhir.healthintersections.com.au/open");
ServletHolder handler = new ServletHolder();
handler.setServlet(testerServlet);
proxyHandler.addServlet(handler, "/fhir/tester/*");
ServletHolder servletHolder = new ServletHolder();
servletHolder.setServlet(myRestfulServer);
proxyHandler.addServlet(servletHolder, "/fhir/context/*");
myServer.setHandler(proxyHandler);
}
@After
public void after() throws Exception {
myServer.stop();
}
@Test
public void testTester() throws Exception {
if (true) return;
myRestfulServer.setProviders(new SearchProvider(), new GlobalHistoryProvider());
myServer.start();
Thread.sleep(9999999L);
}
/**
* Created by dsotnikov on 2/25/2014.
*/
public static class SearchProvider {
private int myNextId = 1;
private HashMap<String, Patient> myIdToPatient;
private static Patient createPatient() {
Patient patient = new Patient();
patient.addIdentifier();
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
patient.getIdentifier().get(0).setValue("00001");
patient.addName();
patient.getName().get(0).addFamily("Test");
patient.getName().get(0).addGiven("PatientOne");
patient.getGender().setText("M");
return patient;
}
public SearchProvider() {
myIdToPatient = new HashMap<String, Patient>();
{
Patient patient = createPatient();
myIdToPatient.put("" + myNextId++, patient);
}
{
Patient patient = new Patient();
patient.getIdentifier().add(new IdentifierDt());
patient.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
patient.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
patient.getIdentifier().get(0).setValue("00002");
patient.getName().add(new HumanNameDt());
patient.getName().get(0).addFamily("Test");
patient.getName().get(0).addGiven("PatientTwo");
patient.getGender().setText("F");
myIdToPatient.put("" + myNextId++, patient);
}
}
@Create
public MethodOutcome createPatient(@ResourceParam Patient thePatient) {
IdDt id = new IdDt(myNextId++);
myIdToPatient.put(id.getValueAsString(), thePatient);
return new MethodOutcome(id);
}
@SuppressWarnings("unused")
@Validate
public MethodOutcome validatePatient(@ResourceParam Patient thePatient) {
MethodOutcome outcome = new MethodOutcome();
outcome.setOperationOutcome(new OperationOutcome());
outcome.getOperationOutcome().addIssue().setDetails("This is a detected issue");
return outcome;
}
@Update
public MethodOutcome updatePatient(@IdParam IdDt theId, @ResourceParam Patient thePatient) {
myIdToPatient.put(theId.getValueAsString(), thePatient);
return new MethodOutcome(theId);
}
@Delete(type=Patient.class)
public MethodOutcome deletePatient(@IdParam IdDt theId) {
myIdToPatient.remove(theId.getValue());
return new MethodOutcome();
}
@Search(type = Patient.class)
public Patient findPatient(@Description(shortDefinition = "The patient's identifier (MRN or other card number). Example system 'urn:hapitest:mrns', example MRN '00002'") @RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
for (Patient next : myIdToPatient.values()) {
for (IdentifierDt nextId : next.getIdentifier()) {
if (nextId.matchesSystemAndValue(theIdentifier)) {
return next;
}
}
}
return null;
}
/**
* Retrieve the resource by its identifier
*
* @param theId
* The resource identity
* @return The resource
*/
@Read(type = Patient.class)
public Patient getPatientById(@IdParam IdDt theId) {
return myIdToPatient.get(theId.getValue());
}
/**
* Retrieve the resource by its identifier
*
* @param theId
* The resource identity
* @return The resource
*/
@History(type = Patient.class)
public List<Patient> getPatientHistory(@IdParam IdDt theId) {
Patient patient = myIdToPatient.get(theId.getValue());
if (patient==null) {
throw new ResourceNotFoundException(Patient.class, theId);
}
ArrayList<Patient> retVal = new ArrayList<Patient>();
for (int i = 0; i < 5;i++) {
Patient pat = createPatient();
pat.setId(theId);
pat.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, ""+i);
retVal.add(pat);
}
return retVal;
}
}
public static class GlobalHistoryProvider {
private InstantDt myLastSince;
private IntegerDt myLastCount;
@History
public List<IResource> getGlobalHistory(@Since InstantDt theSince, @Count IntegerDt theCount) {
myLastSince = theSince;
myLastCount = theCount;
ArrayList<IResource> retVal = new ArrayList<IResource>();
IResource p = SearchProvider.createPatient();
p.setId(new IdDt("1"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, new IdDt("A"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, new InstantDt("2012-01-01T00:00:01"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt("2012-01-01T01:00:01"));
retVal.add(p);
p = SearchProvider.createPatient();
p.setId(new IdDt("1"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, new IdDt("B"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, new InstantDt("2012-01-01T00:00:01"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt("2012-01-01T01:00:03"));
retVal.add(p);
p = createOrganization();
p.setId(new IdDt("1"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, new IdDt("A"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, new InstantDt("2013-01-01T00:00:01"));
p.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, new InstantDt("2013-01-01T01:00:01"));
retVal.add(p);
return retVal;
}
}
private static Organization createOrganization() {
Organization retVal = new Organization();
retVal.addIdentifier();
retVal.getIdentifier().get(0).setUse(IdentifierUseEnum.OFFICIAL);
retVal.getIdentifier().get(0).setSystem(new UriDt("urn:hapitest:mrns"));
retVal.getIdentifier().get(0).setValue("00001");
retVal.getName().setValue("Test Org");
return retVal;
}
}

View File

@ -70,7 +70,8 @@ public class TransactionTest {
httpPost.addHeader("Accept", Constants.CT_ATOM_XML + "; pretty=true");
httpPost.setEntity(new StringEntity(bundleString, ContentType.create(Constants.CT_ATOM_XML, "UTF-8")));
HttpResponse status = ourClient.execute(httpPost);
String responseContent = IOUtils.toString(status.getEntity().getContent());
String responseContent = IOUtils.toString(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
assertEquals(200, status.getStatusLine().getStatusCode());
ourLog.info(responseContent);

View File

@ -1,779 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2011-2013, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Generated on Mon, Feb 3, 2014 23:47+1100 for FHIR v0.80
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://hl7.org/fhir" xmlns:xhtml="http://www.w3.org/1999/xhtml" targetNamespace="http://hl7.org/fhir" elementFormDefault="qualified" version="0.80">
<xs:include schemaLocation="fhir-base.xsd"/>
<xs:element name="Conformance" type="Conformance">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:complexType name="Conformance">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Resource">
<xs:sequence>
<xs:element name="identifier" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>The identifier that is used to identify this conformance statement when it is referenced in a specification, model, design or an instance (should be globally unique OID, UUID, or URI).</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="version" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>The identifier that is used to identify this version of the conformance statement when it is referenced in a specification, model, design or instance. This is an arbitrary value managed by the profile author manually and the value should be a timestamp.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="name" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>A free text natural language name identifying the conformance statement.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="publisher" minOccurs="1" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Name of Organization publishing this conformance statement.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="telecom" minOccurs="0" maxOccurs="unbounded" type="Contact">
<xs:annotation>
<xs:documentation>Contacts for Organization relevant to this conformance statement. The contacts may be a website, email, phone numbers, etc.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="description" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>A free text natural language description of the conformance statement and its use. Typically, this is used when the profile describes a desired rather than an actual solution, for example as a formal expression of requirements as part of an RFP.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="status" minOccurs="0" maxOccurs="1" type="ConformanceStatementStatus">
<xs:annotation>
<xs:documentation>The status of this conformance statement.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="experimental" minOccurs="0" maxOccurs="1" type="boolean">
<xs:annotation>
<xs:documentation>A flag to indicate that this conformance statement is authored for testing purposes (or education/evaluation/marketing), and is not intended to be used for genuine usage.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="date" minOccurs="1" maxOccurs="1" type="dateTime">
<xs:annotation>
<xs:documentation>The date when the conformance statement was published.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="software" type="Conformance.Software" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Software that is covered by this conformance statement. It is used when the profile describes the capabilities of a particular software version, independent of an installation.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="implementation" type="Conformance.Implementation" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Identifies a specific implementation instance that is described by the conformance statement - i.e. a particular installation, rather than the capabilities of a software program.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="fhirVersion" minOccurs="1" maxOccurs="1" type="id">
<xs:annotation>
<xs:documentation>The version of the FHIR specification on which this conformance statement is based.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="acceptUnknown" minOccurs="1" maxOccurs="1" type="boolean">
<xs:annotation>
<xs:documentation>A flag that indicates whether the application accepts unknown elements as part of a resource.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="format" minOccurs="1" maxOccurs="unbounded" type="code">
<xs:annotation>
<xs:documentation>A list of the formats supported by this implementation.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="profile" minOccurs="0" maxOccurs="unbounded" type="ResourceReference">
<xs:annotation>
<xs:documentation>A list of profiles supported by the system. For a server, &quot;supported by the system&quot; means the system hosts/produces a set of recourses, conformant to a particular profile, and allows its clients to search using this profile and to find appropriate data. For a client, it means the system will search by this profile and process data according to the guidance implicit in the profile.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="rest" type="Conformance.Rest" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A definition of the restful capabilities of the solution, if any.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="messaging" type="Conformance.Messaging" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A description of the messaging capabilities of the solution.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="document" type="Conformance.Document" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A document definition.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Software">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="name" minOccurs="1" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Name software is known by.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="version" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>The version identifier for the software covered by this statement.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="releaseDate" minOccurs="0" maxOccurs="1" type="dateTime">
<xs:annotation>
<xs:documentation>Date this version of the software released.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Implementation">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="description" minOccurs="1" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Information about the specific installation that this conformance statement relates to.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="url" minOccurs="0" maxOccurs="1" type="uri">
<xs:annotation>
<xs:documentation>A base URL for the implementation. This forms the base for REST interfaces as well as the mailbox and document interfaces.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Rest">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="mode" minOccurs="1" maxOccurs="1" type="RestfulConformanceMode">
<xs:annotation>
<xs:documentation>Identifies whether this portion of the statement is describing ability to initiate or receive restful operations.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Information about the system's restful capabilities that apply across all applications, such as security.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="security" type="Conformance.Security" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Information about security of implementation.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="resource" type="Conformance.Resource" minOccurs="1" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A specification of the restful capabilities of the solution for a specific resource type.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="operation" type="Conformance.Operation1" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A specification of restful operations supported by the system.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="query" type="Conformance.Query" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Definition of a named query and its parameters and their meaning.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentMailbox" minOccurs="0" maxOccurs="unbounded" type="uri">
<xs:annotation>
<xs:documentation>A list of profiles that this server implements for accepting documents in the mailbox. If this list is empty, then documents are not accepted. The base specification has the profile identifier &quot;http://hl7.org/fhir/documents/mailbox&quot;. Other specifications can declare their own identifier for this purpose.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Security">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="cors" minOccurs="0" maxOccurs="1" type="boolean">
<xs:annotation>
<xs:documentation>Server adds CORS headers when responding to requests - this enables javascript applications to yuse the server.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="service" minOccurs="0" maxOccurs="unbounded" type="CodeableConcept">
<xs:annotation>
<xs:documentation>Types of security services are supported/required by the system.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="description" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>General description of how security works.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="certificate" type="Conformance.Certificate" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Certificates associated with security profiles.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Certificate">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="type" minOccurs="0" maxOccurs="1" type="code">
<xs:annotation>
<xs:documentation>Mime type for certificate.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="blob" minOccurs="0" maxOccurs="1" type="base64Binary">
<xs:annotation>
<xs:documentation>Actual certificate.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Resource">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="type" minOccurs="1" maxOccurs="1" type="code">
<xs:annotation>
<xs:documentation>A type of resource exposed via the restful interface.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="profile" minOccurs="0" maxOccurs="1" type="ResourceReference">
<xs:annotation>
<xs:documentation>A specification of the profile that describes the solution's support for the resource, including any constraints on cardinality, bindings, lengths or other limitations.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="operation" type="Conformance.Operation" minOccurs="1" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Identifies a restful operation supported by the solution.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="readHistory" minOccurs="0" maxOccurs="1" type="boolean">
<xs:annotation>
<xs:documentation>A flag for whether the server is able to return past versions as part of the vRead operation.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="updateCreate" minOccurs="0" maxOccurs="1" type="boolean">
<xs:annotation>
<xs:documentation>A flag to indicate that the server allows the client to create new identities on the server. If the update operation is used (client) or allowed (server) to a new location where a resource doesn't already exist. This means that the server allows the client to create new identities on the server.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="searchInclude" minOccurs="0" maxOccurs="unbounded" type="string">
<xs:annotation>
<xs:documentation>A list of _include values supported by the server.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="searchParam" type="Conformance.SearchParam" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Additional search parameters for implementations to support and/or make use of.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Operation">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="code" minOccurs="1" maxOccurs="1" type="RestfulOperationType">
<xs:annotation>
<xs:documentation>Coded identifier of the operation, supported by the system resource.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Guidance specific to the implementation of this operation, such as 'delete is a logical delete' or 'updates are only allowed with version id' or 'creates permitted from pre-authorized certificates only'.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.SearchParam">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="name" minOccurs="1" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>The name of the search parameter used in the interface.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="definition" minOccurs="0" maxOccurs="1" type="uri">
<xs:annotation>
<xs:documentation>A formal reference to where this parameter was first defined, so that a client can be confident of the meaning of the search parameter.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="type" minOccurs="1" maxOccurs="1" type="SearchParamType">
<xs:annotation>
<xs:documentation>The type of value a search parameter refers to, and how the content is interpreted.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>This allows documentation of any distinct behaviors about how the search parameter is used. For example, text matching algorithms.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="target" minOccurs="0" maxOccurs="unbounded" type="code">
<xs:annotation>
<xs:documentation>Types of resource (if a resource is referenced).</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="chain" minOccurs="0" maxOccurs="unbounded" type="string">
<xs:annotation>
<xs:documentation>Chained names supported.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Operation1">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="code" minOccurs="1" maxOccurs="1" type="RestfulOperationSystem">
<xs:annotation>
<xs:documentation>A coded identifier of the operation, supported by the system.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Guidance specific to the implementation of this operation, such as limitations on the kind of transactions allowed, or information about system wide search is implemented.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Query">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="name" minOccurs="1" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>The name of a query, which is used in the _query parameter when the query is called.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="definition" minOccurs="1" maxOccurs="1" type="uri">
<xs:annotation>
<xs:documentation>Identifies the custom query, defined either in FHIR core or another profile.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Additional information about how the query functions in this particular implementation.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="parameter" type="Conformance.SearchParam" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Identifies which of the parameters for the named query are supported.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Messaging">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="endpoint" minOccurs="0" maxOccurs="1" type="uri">
<xs:annotation>
<xs:documentation>An address to which messages and/or replies are to be sent.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="reliableCache" minOccurs="0" maxOccurs="1" type="integer">
<xs:annotation>
<xs:documentation>Length if the receiver's reliable messaging cache (if a receiver) or how long the cache length on the receiver should be (if a sender).</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Documentation about the system's messaging capabilities for this endpoint not otherwise documented by the conformance statement. For example, process for becoming an authorized messaging exchange partner.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="event" type="Conformance.Event" minOccurs="1" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A description of the solution's support for an event at this end point.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Event">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="code" minOccurs="1" maxOccurs="1" type="Coding">
<xs:annotation>
<xs:documentation>A coded identifier of a supported messaging event.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="category" minOccurs="0" maxOccurs="1" type="MessageSignificanceCategory">
<xs:annotation>
<xs:documentation>The impact of the content of the message.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="mode" minOccurs="1" maxOccurs="1" type="ConformanceEventMode">
<xs:annotation>
<xs:documentation>The mode of this event declaration - whether application is sender or receiver.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="protocol" minOccurs="0" maxOccurs="unbounded" type="Coding">
<xs:annotation>
<xs:documentation>A list of the messaging transport protocol(s) identifiers, supported by this endpoint.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="focus" minOccurs="1" maxOccurs="1" type="code">
<xs:annotation>
<xs:documentation>A resource associated with the event. This is the resource that defines the event.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="request" minOccurs="1" maxOccurs="1" type="ResourceReference">
<xs:annotation>
<xs:documentation>Information about the request for this event.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="response" minOccurs="1" maxOccurs="1" type="ResourceReference">
<xs:annotation>
<xs:documentation>Information about the response for this event.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>Guidance on how this event is handled, such as internal system trigger points, business rules, etc.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Conformance.Document">
<xs:annotation>
<xs:documentation>A conformance statement is a set of requirements for a desired implementation or a description of how a target application fulfills those requirements in a particular implementation.</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="BackboneElement">
<xs:sequence>
<xs:element name="mode" minOccurs="1" maxOccurs="1" type="DocumentMode">
<xs:annotation>
<xs:documentation>Mode of this document declaration - whether application is producer or consumer.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="documentation" minOccurs="0" maxOccurs="1" type="string">
<xs:annotation>
<xs:documentation>A description of how the application supports or uses the specified document profile. For example, when are documents created, what action is taken with consumed documents, etc.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="profile" minOccurs="1" maxOccurs="1" type="ResourceReference">
<xs:annotation>
<xs:documentation>A constraint on a resource used in the document.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="DocumentMode-list">
<xs:restriction base="xs:string">
<xs:enumeration value="producer">
<xs:annotation>
<xs:documentation>The application produces documents of the specified type.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="consumer">
<xs:annotation>
<xs:documentation>The application consumes documents of the specified type.</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="DocumentMode">
<xs:annotation>
<xs:documentation>Whether the application produces or consumes documents</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="value" type="DocumentMode-list" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="RestfulConformanceMode-list">
<xs:restriction base="xs:string">
<xs:enumeration value="client">
<xs:annotation>
<xs:documentation>The application acts as a server for this resource.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="server">
<xs:annotation>
<xs:documentation>The application acts as a client for this resource.</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="RestfulConformanceMode">
<xs:annotation>
<xs:documentation>The mode of a RESTful conformance statement</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="value" type="RestfulConformanceMode-list" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="ConformanceEventMode-list">
<xs:restriction base="xs:string">
<xs:enumeration value="sender">
<xs:annotation>
<xs:documentation>The application sends requests and receives responses.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="receiver">
<xs:annotation>
<xs:documentation>The application receives requests and sends responses.</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="ConformanceEventMode">
<xs:annotation>
<xs:documentation>The mode of a message conformance statement</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="value" type="ConformanceEventMode-list" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="MessageSignificanceCategory-list">
<xs:restriction base="xs:string">
<xs:enumeration value="Consequence">
<xs:annotation>
<xs:documentation>The message represents/requests a change that should not be processed more than once. E.g. Making a booking for an appointment.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="Currency">
<xs:annotation>
<xs:documentation>The message represents a response to query for current information. Retrospective processing is wrong and/or wasteful.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="Notification">
<xs:annotation>
<xs:documentation>The content is not necessarily intended to be current, and it can be reprocessed, though there may be version issues created by processing old notifications.</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="MessageSignificanceCategory">
<xs:annotation>
<xs:documentation>The impact of the content of a message</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="value" type="MessageSignificanceCategory-list" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="RestfulOperationType-list">
<xs:restriction base="xs:string">
<xs:enumeration value="read">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="vread">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="update">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="delete">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="history-instance">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="validate">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="history-type">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="create">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="search-type">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="RestfulOperationType">
<xs:annotation>
<xs:documentation>Operations supported by REST at the type or instance level</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="value" type="RestfulOperationType-list" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="ConformanceStatementStatus-list">
<xs:restriction base="xs:string">
<xs:enumeration value="draft">
<xs:annotation>
<xs:documentation>This conformance statement is still under development.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="active">
<xs:annotation>
<xs:documentation>This conformance statement is ready for use in production systems.</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="retired">
<xs:annotation>
<xs:documentation>This conformance statement has been withdrawn or superceded and should no longer be used.</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="ConformanceStatementStatus">
<xs:annotation>
<xs:documentation>The status of this conformance statement</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="value" type="ConformanceStatementStatus-list" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="RestfulOperationSystem-list">
<xs:restriction base="xs:string">
<xs:enumeration value="transaction">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="search-system">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="history-system">
<xs:annotation>
<xs:documentation></xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="RestfulOperationSystem">
<xs:annotation>
<xs:documentation>Operations supported by REST at the system level</xs:documentation>
<xs:documentation>If the element is present, it must have either a @value, an @id, or extensions</xs:documentation>
</xs:annotation>
<xs:complexContent>
<xs:extension base="Element">
<xs:attribute name="value" type="RestfulOperationSystem-list" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?><Patient xmlns="http://hl7.org/fhir">
<text>
<status value="generated"/>

View File

@ -18,6 +18,7 @@
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">

View File

@ -6,11 +6,21 @@
<project>hapi-fhir-base</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
@ -18,7 +28,10 @@
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

View File

@ -1,7 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="hapi-fhir-jpaserver-base">
<wb-resource deploy-path="/" source-path="/src/main/java"/>
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
</wb-module>
</project-modules>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="java" version="1.6"/>
<installed facet="jst.utility" version="1.0"/>
</faceted-project>

View File

@ -0,0 +1,2 @@
disabled=06target
eclipse.preferences.version=1

View File

@ -8,7 +8,6 @@
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-base</artifactId>
<packaging>jar</packaging>
@ -24,7 +23,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.1</version>
<version>${logback-version}</version>
<scope>test</scope>
</dependency>
<dependency>
@ -37,13 +36,7 @@
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>${hamcrest_version}</version>
</dependency>
<!-- Database -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
<!-- Test Database -->
@ -51,7 +44,15 @@
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>${derby_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
<!-- <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.3.2</version> </dependency> -->
<!-- Spring -->
@ -156,18 +157,6 @@
<properties>
<junit_version>4.11</junit_version>
<derby_version>10.10.2.0</derby_version>
<guava_version>14.0.1</guava_version>
<hamcrest_version>1.3</hamcrest_version>
<!-- <hibernate_version>4.3.5.Final</hibernate_version>-->
<hibernate_version>4.2.12.Final</hibernate_version>
<hibernate_validator_version>5.1.0.Final</hibernate_validator_version>
<jetty_version>9.1.1.v20140108</jetty_version>
<mockito_version>1.9.5</mockito_version>
<slf4j_version>1.7.2</slf4j_version>
<spring_version>4.0.1.RELEASE</spring_version>
<skip-hib4>false</skip-hib4>
</properties>

View File

@ -5,7 +5,6 @@ import static org.apache.commons.lang3.StringUtils.*;
import java.io.UnsupportedEncodingException;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@ -28,7 +27,6 @@ import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import ca.uhn.fhir.context.ConfigurationException;
@ -79,30 +77,31 @@ import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
public abstract class BaseFhirDao {
@Autowired(required=true)
@Autowired(required = true)
private FhirContext myContext;
@PersistenceContext(name = "FHIR_UT", type = PersistenceContextType.TRANSACTION, unitName = "FHIR_UT")
private EntityManager myEntityManager;
@Autowired
private List<IFhirResourceDao<?>> myResourceDaos;
private Map<Class<? extends IResource>, IFhirResourceDao<?>> myResourceTypeToDao;
protected void loadResourcesById(Set<IdDt> theIncludePids, List<IResource> theResourceListToPopulate) {
Set<Long> pids = new HashSet<Long>();
for (IdDt next : theIncludePids) {
pids.add(next.getIdPartAsLong());
}
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<ResourceTable> cq = builder.createQuery(ResourceTable.class);
Root<ResourceTable> from = cq.from(ResourceTable.class);
// cq.where(builder.equal(from.get("myResourceType"), getContext().getResourceDefinition(myResourceType).getName()));
// if (theIncludePids != null) {
cq.where(from.get("myId").in(pids));
// }
// cq.where(builder.equal(from.get("myResourceType"),
// getContext().getResourceDefinition(myResourceType).getName()));
// if (theIncludePids != null) {
cq.where(from.get("myId").in(pids));
// }
TypedQuery<ResourceTable> q = myEntityManager.createQuery(cq);
for (ResourceTable next : q.getResultList()) {
@ -193,7 +192,7 @@ public abstract class BaseFhirDao {
}
}
private void searchHistoryHistory(String theResourceName, Long theResourceId, Date theSince,Date theEnd, Integer theLimit, List<HistoryTuple> tuples) {
private void searchHistoryHistory(String theResourceName, Long theResourceId, Date theSince, Date theEnd, Integer theLimit, List<HistoryTuple> tuples) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
Root<?> from = cq.from(ResourceHistoryTable.class);
@ -232,12 +231,12 @@ public abstract class BaseFhirDao {
}
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseFhirDao.class);
private void searchHistoryHistory(List<HistoryTuple> theTuples, List<BaseHasResource> theRetVal) {
Collection<HistoryTuple> tuples = Collections2.filter(theTuples, new com.google.common.base.Predicate<HistoryTuple>() {
@Override
public boolean apply(HistoryTuple theInput) {
return theInput.isHistory()==true;
return theInput.isHistory() == true;
}
});
Collection<Long> ids = Collections2.transform(tuples, new Function<HistoryTuple, Long>() {
@ -249,7 +248,7 @@ public abstract class BaseFhirDao {
if (ids.isEmpty()) {
return;
}
ourLog.info("Retrieving {} history elements from ResourceHistoryTable", ids.size());
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
@ -423,8 +422,7 @@ public abstract class BaseFhirDao {
if (nextObject instanceof QuantityDt) {
QuantityDt nextValue = (QuantityDt) nextObject;
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, nextValue.getValue().getValue(), nextValue.getSystem().getValueAsString(),
nextValue.getUnits().getValue());
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, nextValue.getValue().getValue(), nextValue.getSystem().getValueAsString(), nextValue.getUnits().getValue());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
} else {
@ -507,8 +505,7 @@ public abstract class BaseFhirDao {
} else if (nextObject instanceof ContactDt) {
ContactDt nextContact = (ContactDt) nextObject;
if (nextContact.getValue().isEmpty() == false) {
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextContact.getValue().getValueAsString()), nextContact
.getValue().getValueAsString());
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, normalizeString(nextContact.getValue().getValueAsString()), nextContact.getValue().getValueAsString());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
}
@ -610,19 +607,19 @@ public abstract class BaseFhirDao {
protected IBundleProvider history(String theResourceName, Long theId, Date theSince) {
final List<HistoryTuple> tuples = new ArrayList<HistoryTuple>();
final InstantDt end = createHistoryToTimestamp();
StopWatch timer = new StopWatch();
int limit = 10000;
// Get list of IDs
searchHistoryCurrentVersion(theResourceName, theId, theSince, end.getValue(), limit, tuples);
assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated());
ourLog.info("Retrieved {} history IDs from current versions in {} ms", tuples.size(), timer.getMillisAndRestart());
searchHistoryHistory(theResourceName, theId, theSince, end.getValue() , limit, tuples);
searchHistoryHistory(theResourceName, theId, theSince, end.getValue(), limit, tuples);
assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated());
ourLog.info("Retrieved {} history IDs from previous versions in {} ms", tuples.size(), timer.getMillisAndRestart());
@ -631,21 +628,21 @@ public abstract class BaseFhirDao {
assert tuples.size() < 2 || !tuples.get(tuples.size() - 2).getUpdated().before(tuples.get(tuples.size() - 1).getUpdated());
return new IBundleProvider() {
@Override
public int size() {
return tuples.size();
}
@Override
public List<IResource> getResources(int theFromIndex, int theToIndex) {
StopWatch timer = new StopWatch();
List<BaseHasResource> resEntities = Lists.newArrayList();
List<HistoryTuple> tupleSubList = tuples.subList(theFromIndex, theToIndex);
searchHistoryCurrentVersion(tupleSubList, resEntities);
ourLog.info("Loaded history from current versions in {} ms", timer.getMillisAndRestart());
searchHistoryHistory(tupleSubList, resEntities);
ourLog.info("Loaded history from previous versions in {} ms", timer.getMillisAndRestart());
@ -656,7 +653,7 @@ public abstract class BaseFhirDao {
}
});
int limit = theToIndex-theFromIndex;
int limit = theToIndex - theFromIndex;
if (resEntities.size() > limit) {
resEntities = resEntities.subList(0, limit);
}
@ -667,7 +664,7 @@ public abstract class BaseFhirDao {
}
return retVal;
}
@Override
public InstantDt getPublished() {
return end;
@ -676,7 +673,8 @@ public abstract class BaseFhirDao {
}
InstantDt createHistoryToTimestamp() {
// final InstantDt end = new InstantDt(DateUtils.addSeconds(DateUtils.truncate(new Date(), Calendar.SECOND), -1));
// final InstantDt end = new InstantDt(DateUtils.addSeconds(DateUtils.truncate(new Date(), Calendar.SECOND),
// -1));
return InstantDt.withCurrentTime();
}
@ -716,22 +714,31 @@ public abstract class BaseFhirDao {
theEntity.setUpdated(new Date());
theEntity.setResourceType(toResourceName(theResource));
List<ResourceReferenceDt> refs = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, ResourceReferenceDt.class);
for (ResourceReferenceDt nextRef : refs) {
if (nextRef.getReference().isEmpty()==false) {
if (nextRef.getReference().hasVersionIdPart()) {
nextRef.setReference(nextRef.getReference().toUnqualifiedVersionless());
}
}
}
String encoded = myConfig.getResourceEncoding().newParser(myContext).encodeResourceToString(theResource);
ResourceEncodingEnum encoding = myConfig.getResourceEncoding();
ResourceEncodingEnum encoding = myConfig.getResourceEncoding();
theEntity.setEncoding(encoding);
try {
switch (encoding) {
case JSON:
switch (encoding) {
case JSON:
theEntity.setResource(encoded.getBytes("UTF-8"));
break;
case JSONC:
theEntity.setResource(GZipUtil.compress(encoded));
break;
}
break;
case JSONC:
theEntity.setResource(GZipUtil.compress(encoded));
break;
}
} catch (UnsupportedEncodingException e) {
}
TagList tagList = (TagList) theResource.getResourceMetadata().get(ResourceMetadataKeyEnum.TAG_LIST);
if (tagList != null) {
for (Tag next : tagList) {
@ -756,7 +763,7 @@ public abstract class BaseFhirDao {
}
protected <T extends IResource> T toResource(Class<T> theResourceType, BaseHasResource theEntity) {
String resourceText=null;
String resourceText = null;
switch (theEntity.getEncoding()) {
case JSON:
try {
@ -769,16 +776,22 @@ public abstract class BaseFhirDao {
resourceText = GZipUtil.decompress(theEntity.getResource());
break;
}
IParser parser = theEntity.getEncoding().newParser(getContext());
T retVal = parser.parseResource(theResourceType, resourceText);
retVal.setId(theEntity.getIdDt());
retVal.getResourceMetadata().put(ResourceMetadataKeyEnum.VERSION_ID, theEntity.getVersion());
retVal.getResourceMetadata().put(ResourceMetadataKeyEnum.PUBLISHED, theEntity.getPublished());
retVal.getResourceMetadata().put(ResourceMetadataKeyEnum.UPDATED, theEntity.getUpdated());
if (theEntity.getTags().size() > 0) {
if (theEntity.getDeleted()!=null) {
ResourceMetadataKeyEnum.DELETED_AT.put(retVal, new InstantDt(theEntity.getDeleted()));
}
Collection<? extends BaseTag> tags = theEntity.getTags();
if (tags.size() > 0) {
TagList tagList = new TagList();
for (BaseTag next : theEntity.getTags()) {
for (BaseTag next : tags) {
tagList.add(new Tag(next.getTag().getScheme(), next.getTag().getTerm(), next.getTag().getLabel()));
}
retVal.getResourceMetadata().put(ResourceMetadataKeyEnum.TAG_LIST, tagList);
@ -794,7 +807,7 @@ public abstract class BaseFhirDao {
return myContext.getResourceDefinition(theResourceType).getName();
}
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory) {
protected ResourceTable updateEntity(final IResource theResource, ResourceTable entity, boolean theUpdateHistory, boolean theDelete) {
if (entity.getPublished() == null) {
entity.setPublished(new Date());
}
@ -812,25 +825,43 @@ public abstract class BaseFhirDao {
Collection<ResourceIndexedSearchParamDate> paramsDate = new ArrayList<ResourceIndexedSearchParamDate>(entity.getParamsDate());
Collection<ResourceLink> resourceLinks = new ArrayList<ResourceLink>(entity.getResourceLinks());
final List<ResourceIndexedSearchParamString> stringParams = extractSearchParamStrings(entity, theResource);
final List<ResourceIndexedSearchParamToken> tokenParams = extractSearchParamTokens(entity, theResource);
final List<ResourceIndexedSearchParamNumber> numberParams = extractSearchParamNumber(entity, theResource);
final List<ResourceIndexedSearchParamDate> dateParams = extractSearchParamDates(entity, theResource);
final List<ResourceLink> links = extractResourceLinks(entity, theResource);
final List<ResourceIndexedSearchParamString> stringParams;
final List<ResourceIndexedSearchParamToken> tokenParams;
final List<ResourceIndexedSearchParamNumber> numberParams;
final List<ResourceIndexedSearchParamDate> dateParams;
final List<ResourceLink> links;
if (theDelete) {
stringParams = Collections.emptyList();
tokenParams = Collections.emptyList();
numberParams = Collections.emptyList();
dateParams = Collections.emptyList();
links = Collections.emptyList();
entity.setDeleted(new Date());
entity.setUpdated(new Date());
} else {
populateResourceIntoEntity(theResource, entity);
stringParams = extractSearchParamStrings(entity, theResource);
tokenParams = extractSearchParamTokens(entity, theResource);
numberParams = extractSearchParamNumber(entity, theResource);
dateParams = extractSearchParamDates(entity, theResource);
links = extractResourceLinks(entity, theResource);
populateResourceIntoEntity(theResource, entity);
entity.setUpdated(new Date());
entity.setParamsString(stringParams);
entity.setParamsStringPopulated(stringParams.isEmpty()==false);
entity.setParamsToken(tokenParams);
entity.setParamsTokenPopulated(tokenParams.isEmpty()==false);
entity.setParamsNumber(numberParams);
entity.setParamsNumberPopulated(numberParams.isEmpty()==false);
entity.setParamsDate(dateParams);
entity.setParamsDatePopulated(dateParams.isEmpty()==false);
entity.setResourceLinks(links);
entity.setHasLinks(links.isEmpty()==false);
entity.setUpdated(new Date());
entity.setParamsString(stringParams);
entity.setParamsStringPopulated(stringParams.isEmpty() == false);
entity.setParamsToken(tokenParams);
entity.setParamsTokenPopulated(tokenParams.isEmpty() == false);
entity.setParamsNumber(numberParams);
entity.setParamsNumberPopulated(numberParams.isEmpty() == false);
entity.setParamsDate(dateParams);
entity.setParamsDatePopulated(dateParams.isEmpty() == false);
entity.setResourceLinks(links);
entity.setHasLinks(links.isEmpty() == false);
}
if (entity.getId() == null) {
myEntityManager.persist(entity);
@ -846,7 +877,7 @@ public abstract class BaseFhirDao {
for (ResourceIndexedSearchParamString next : stringParams) {
myEntityManager.persist(next);
}
if (entity.isParamsTokenPopulated()) {
for (ResourceIndexedSearchParamToken next : paramsToken) {
myEntityManager.remove(next);
@ -882,10 +913,13 @@ public abstract class BaseFhirDao {
for (ResourceLink next : links) {
myEntityManager.persist(next);
}
myEntityManager.flush();
theResource.setId(new IdDt(entity.getResourceType(), entity.getId().toString(), Long.toString(entity.getVersion())));
myEntityManager.flush();
if (theResource!=null) {
theResource.setId(new IdDt(entity.getResourceType(), entity.getId().toString(), Long.toString(entity.getVersion())));
}
return entity;
}

View File

@ -70,6 +70,7 @@ import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.util.FhirTerser;
@ -479,7 +480,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
ResourceTable entity = new ResourceTable();
entity.setResourceType(toResourceName(theResource));
updateEntity(theResource, entity, false);
updateEntity(theResource, entity, false, false);
MethodOutcome outcome = toMethodOutcome(entity);
return outcome;
@ -617,6 +618,12 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
BaseHasResource entity = readEntity(theId);
T retVal = toResource(myResourceType, entity);
InstantDt deleted = ResourceMetadataKeyEnum.DELETED_AT.get(retVal);
if (deleted != null && !deleted.isEmpty()) {
throw new ResourceGoneException("Resource was deleted at " + deleted.getValueAsString());
}
return retVal;
}
@ -727,7 +734,7 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
for (Include next : theParams.getIncludes()) {
for (IResource nextResource : retVal) {
assert myResourceType.isAssignableFrom(nextResource.getClass());
List<Object> values = t.getValues(nextResource, next.getValue());
for (Object object : values) {
if (object == null) {
@ -764,8 +771,6 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
};
}
private void loadResourcesByPid(Collection<Long> theIncludePids, List<IResource> theResourceListToPopulate) {
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
CriteriaQuery<ResourceTable> cq = builder.createQuery(ResourceTable.class);
@ -952,7 +957,23 @@ public class FhirResourceDao<T extends IResource> extends BaseFhirDao implements
// });
final ResourceTable entity = readEntityLatestVersion(theId);
ResourceTable savedEntity = updateEntity(theResource, entity, true);
if (theId.hasVersionIdPart() && theId.getVersionIdPartAsLong().longValue() != entity.getVersion()) {
throw new InvalidRequestException("Trying to update " + theId + " but this is not the current version");
}
ResourceTable savedEntity = updateEntity(theResource, entity, true, false);
return toMethodOutcome(savedEntity);
}
@Override
public MethodOutcome delete(IdDt theId) {
final ResourceTable entity = readEntityLatestVersion(theId);
if (theId.hasVersionIdPart() && theId.getVersionIdPartAsLong().longValue() != entity.getVersion()) {
throw new InvalidRequestException("Trying to update " + theId + " but this is not the current version");
}
ResourceTable savedEntity = updateEntity(null, entity, true, true);
return toMethodOutcome(savedEntity);
}

View File

@ -123,7 +123,7 @@ public class FhirSystemDao extends BaseFhirDao implements IFhirSystemDao {
for (int i = 0; i < theResources.size(); i++) {
IResource resource = theResources.get(i);
ResourceTable table = persistedResources.get(i);
updateEntity(resource, table, table.getId() != null);
updateEntity(resource, table, table.getId() != null, false);
}
long delay = System.currentTimeMillis() - start;

View File

@ -20,6 +20,8 @@ public interface IFhirResourceDao<T extends IResource> {
MethodOutcome create(T theResource);
MethodOutcome delete(IdDt theResource);
TagList getAllResourceTags();
Class<T> getResourceType();

View File

@ -17,7 +17,11 @@ import ca.uhn.fhir.model.primitive.InstantDt;
@MappedSuperclass
public abstract class BaseHasResource {
@Column(name = "RES_ENCODING", nullable = false, length=5)
@Column(name = "RES_DELETED_AT", nullable = true)
@Temporal(TemporalType.TIMESTAMP)
private Date myDeleted;
@Column(name = "RES_ENCODING", nullable = false, length = 5)
@Enumerated(EnumType.STRING)
private ResourceEncodingEnum myEncoding;
@ -33,14 +37,16 @@ public abstract class BaseHasResource {
@Column(name = "RES_UPDATED", nullable = false)
private Date myUpdated;
public abstract BaseTag addTag(TagDefinition theDef);
public Date getDeleted() {
return myDeleted;
}
public ResourceEncodingEnum getEncoding() {
return myEncoding;
}
public abstract String getResourceType();
public abstract Collection<? extends BaseTag> getTags();
public abstract IdDt getIdDt();
public InstantDt getPublished() {
@ -51,12 +57,20 @@ public abstract class BaseHasResource {
return myResource;
}
public abstract String getResourceType();
public abstract Collection<? extends BaseTag> getTags();
public InstantDt getUpdated() {
return new InstantDt(myUpdated);
}
public abstract long getVersion();
public void setDeleted(Date theDate) {
myDeleted = theDate;
}
public void setEncoding(ResourceEncodingEnum theEncoding) {
myEncoding = theEncoding;
}
@ -81,6 +95,4 @@ public abstract class BaseHasResource {
myUpdated = theUpdated.getValue();
}
public abstract BaseTag addTag(TagDefinition theDef);
}

View File

@ -19,6 +19,7 @@ public class ResourceHistoryTag extends BaseTag implements Serializable {
@GeneratedValue(strategy=GenerationType.AUTO)
@Id
@Column(name = "PID")
private Long myId;
@ManyToOne()

View File

@ -28,10 +28,10 @@ import ca.uhn.fhir.rest.server.Constants;
@Inheritance(strategy = InheritanceType.JOINED)
@org.hibernate.annotations.Table(appliesTo = "HFJ_RESOURCE", indexes = { @Index(name = "IDX_RES_DATE", columnNames = { "RES_UPDATED" }) })
public class ResourceTable extends BaseHasResource implements Serializable {
static final int RESTYPE_LEN = 30;
private static final long serialVersionUID = 1L;
static final int RESTYPE_LEN = 30;
@Column(name = "SP_HAS_LINKS")
private boolean myHasLinks;
@ -256,6 +256,7 @@ public class ResourceTable extends BaseHasResource implements Serializable {
retVal.setUpdated(getUpdated());
retVal.setEncoding(getEncoding());
retVal.setResource(getResource());
retVal.setDeleted(getDeleted());
for (ResourceTag next : getTags()) {
retVal.addTag(next);

View File

@ -1,17 +1,19 @@
package ca.uhn.fhir.jpa.provider;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
import ca.uhn.fhir.model.dstu.valueset.IssueSeverityEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.GetTags;
import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.annotation.IdParam;
@ -19,13 +21,16 @@ import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.annotation.Validate;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.IResourceProvider;
public class JpaResourceProvider<T extends IResource> implements IResourceProvider {
private FhirContext myContext = new FhirContext();
@Autowired(required=true)
private FhirContext myContext;
private IFhirResourceDao<T> myDao;
public JpaResourceProvider() {
@ -40,7 +45,12 @@ public class JpaResourceProvider<T extends IResource> implements IResourceProvid
public MethodOutcome create(@ResourceParam T theResource) {
return myDao.create(theResource);
}
@Delete
public MethodOutcome delete(@IdParam IdDt theResource) {
return myDao.delete(theResource);
}
public FhirContext getContext() {
return myContext;
}
@ -50,13 +60,13 @@ public class JpaResourceProvider<T extends IResource> implements IResourceProvid
}
@History
public IBundleProvider getHistoryForResourceType(@Since Date theDate) {
return myDao.history(theDate);
public IBundleProvider getHistoryForResourceInstance(@IdParam IdDt theId, @Since Date theDate) {
return myDao.history(theId.getIdPartAsLong(), theDate);
}
@History
public IBundleProvider getHistoryForResourceInstance(@IdParam IdDt theId, @Since Date theDate) {
return myDao.history(theId.getIdPartAsLong(), theDate);
public IBundleProvider getHistoryForResourceType(@Since Date theDate) {
return myDao.history(theDate);
}
@Override
@ -65,13 +75,13 @@ public class JpaResourceProvider<T extends IResource> implements IResourceProvid
}
@GetTags
public TagList getTagsForResourceType() {
return myDao.getAllResourceTags();
public TagList getTagsForResourceInstance(@IdParam IdDt theResourceId) {
return myDao.getTags(theResourceId);
}
@GetTags
public TagList getTagsForResourceInstance(@IdParam IdDt theResourceId) {
return myDao.getTags(theResourceId);
public TagList getTagsForResourceType() {
return myDao.getAllResourceTags();
}
@Read(version=true)
@ -79,6 +89,10 @@ public class JpaResourceProvider<T extends IResource> implements IResourceProvid
return myDao.read(theId);
}
public void setContext(FhirContext theContext) {
myContext = theContext;
}
@Required
public void setDao(IFhirResourceDao<T> theDao) {
myDao = theDao;
@ -89,4 +103,12 @@ public class JpaResourceProvider<T extends IResource> implements IResourceProvid
return myDao.update(theResource, theId);
}
@Validate
public MethodOutcome validate(@ResourceParam T theResource) {
MethodOutcome retVal = new MethodOutcome();
retVal.setOperationOutcome(new OperationOutcome());
retVal.getOperationOutcome().addIssue().setSeverity(IssueSeverityEnum.INFORMATION).setDetails("Resource validates successfully");
return retVal;
}
}

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@ -43,6 +43,7 @@ import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
public class FhirResourceDaoTest {
@ -54,10 +55,28 @@ public class FhirResourceDaoTest {
private static IFhirResourceDao<DiagnosticReport> ourDiagnosticReportDao;
private static IFhirResourceDao<Organization> ourOrganizationDao;
private static IFhirResourceDao<Location> ourLocationDao;
private static Date ourTestStarted;
private static IFhirResourceDao<Encounter> ourEncounterDao;
@Test
public void testStoreUnversionedResources() {
Organization o1 = new Organization();
o1.getName().setValue("AAA");
IdDt o1id = ourOrganizationDao.create(o1).getId();
assertTrue(o1id.hasVersionIdPart());
Patient p1 = new Patient();
p1.addName().addFamily("AAAA");
p1.getManagingOrganization().setReference(o1id);
IdDt p1id = ourPatientDao.create(p1).getId();
p1 = ourPatientDao.read(p1id);
assertFalse(p1.getManagingOrganization().getReference().hasVersionIdPart());
assertEquals(o1id.toUnqualifiedVersionless(), p1.getManagingOrganization().getReference().toUnqualifiedVersionless());
}
@Test
public void testIdParam() {
Patient patient = new Patient();
@ -71,19 +90,19 @@ public class FhirResourceDaoTest {
Date now = new Date();
{
Patient retrieved = ourPatientDao.read(outcome.getId());
InstantDt published = (InstantDt) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
InstantDt updated = (InstantDt) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
assertTrue(published.before(now));
assertTrue(updated.before(now));
Patient retrieved = ourPatientDao.read(outcome.getId());
InstantDt published = (InstantDt) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
InstantDt updated = (InstantDt) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
assertTrue(published.before(now));
assertTrue(updated.before(now));
}
// Now search by _id
{
SearchParameterMap paramMap = new SearchParameterMap();
paramMap.add("_id", new StringParam(outcome.getId().getIdPart()));
List<Patient> ret = toList(ourPatientDao.search(paramMap));
assertEquals(1,ret.size());
assertEquals(1, ret.size());
Patient p = ret.get(0);
assertEquals("Tester", p.getNameFirstRep().getFamilyAsSingleString());
}
@ -92,7 +111,7 @@ public class FhirResourceDaoTest {
paramMap.add("_id", new StringParam(outcome.getId().getIdPart()));
paramMap.add(Patient.SP_NAME, new StringParam("tester"));
List<Patient> ret = toList(ourPatientDao.search(paramMap));
assertEquals(1,ret.size());
assertEquals(1, ret.size());
Patient p = ret.get(0);
assertEquals("Tester", p.getNameFirstRep().getFamilyAsSingleString());
}
@ -101,7 +120,7 @@ public class FhirResourceDaoTest {
paramMap.add(Patient.SP_NAME, new StringParam("tester"));
paramMap.add("_id", new StringParam(outcome.getId().getIdPart()));
List<Patient> ret = toList(ourPatientDao.search(paramMap));
assertEquals(1,ret.size());
assertEquals(1, ret.size());
Patient p = ret.get(0);
assertEquals("Tester", p.getNameFirstRep().getFamilyAsSingleString());
}
@ -110,7 +129,7 @@ public class FhirResourceDaoTest {
paramMap.add(Patient.SP_NAME, new StringParam("tester"));
paramMap.add("_id", new StringParam("000"));
List<Patient> ret = toList(ourPatientDao.search(paramMap));
assertEquals(0,ret.size());
assertEquals(0, ret.size());
}
}
@ -166,7 +185,7 @@ public class FhirResourceDaoTest {
assertEquals(1, found.size());
// If this throws an exception, that would be an acceptable outcome as well..
found = toList(ourPatientDao.search(Patient.SP_BIRTHDATE+"AAAA", new QualifiedDateParam(QuantityCompararatorEnum.GREATERTHAN, "2000-01-01")));
found = toList(ourPatientDao.search(Patient.SP_BIRTHDATE + "AAAA", new QualifiedDateParam(QuantityCompararatorEnum.GREATERTHAN, "2000-01-01")));
assertEquals(0, found.size());
}
@ -221,12 +240,12 @@ public class FhirResourceDaoTest {
assertEquals(1, found.size());
assertEquals(id, found.get(0).getId().getIdPartAsLong().longValue());
// found = ourPatientDao.search(Patient.SP_GENDER, new IdentifierDt(null, "M"));
// assertEquals(1, found.size());
// assertEquals(id, found.get(0).getId().asLong().longValue());
//
// found = ourPatientDao.search(Patient.SP_GENDER, new IdentifierDt(null, "F"));
// assertEquals(0, found.size());
// found = ourPatientDao.search(Patient.SP_GENDER, new IdentifierDt(null, "M"));
// assertEquals(1, found.size());
// assertEquals(id, found.get(0).getId().asLong().longValue());
//
// found = ourPatientDao.search(Patient.SP_GENDER, new IdentifierDt(null, "F"));
// assertEquals(0, found.size());
SearchParameterMap map = new SearchParameterMap();
map.put(Patient.SP_IDENTIFIER, new ArrayList<List<IQueryParameterType>>());
@ -235,7 +254,7 @@ public class FhirResourceDaoTest {
map.put(Patient.SP_GENDER, new ArrayList<List<IQueryParameterType>>());
map.get(Patient.SP_GENDER).add(new ArrayList<IQueryParameterType>());
map.get(Patient.SP_GENDER).get(0).add(new IdentifierDt(AdministrativeGenderCodesEnum.M.getSystem(), "M"));
found =toList( ourPatientDao.search(map));
found = toList(ourPatientDao.search(map));
assertEquals(1, found.size());
assertEquals(id, found.get(0).getId().getIdPartAsLong().longValue());
@ -246,7 +265,7 @@ public class FhirResourceDaoTest {
map.put(Patient.SP_GENDER, new ArrayList<List<IQueryParameterType>>());
map.get(Patient.SP_GENDER).add(new ArrayList<IQueryParameterType>());
map.get(Patient.SP_GENDER).get(0).add(new IdentifierDt(AdministrativeGenderCodesEnum.M.getSystem(), "F"));
found =toList( ourPatientDao.search(map));
found = toList(ourPatientDao.search(map));
assertEquals(0, found.size());
}
@ -311,7 +330,6 @@ public class FhirResourceDaoTest {
assertEquals(1, patients.size());
assertEquals(id1.getIdPart(), patients.get(0).getId().getIdPart());
params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_FAMILY, new StringDt("testSearchNameParam01Foo"));
patients = toList(ourPatientDao.search(params));
@ -437,14 +455,77 @@ public class FhirResourceDaoTest {
assertEquals(0, patients.size());
}
@Test
public void testDelete() {
int initialHistory = ourPatientDao.history(null).size();
IdDt id1;
IdDt id2;
IdDt id2b;
{
Patient patient = new Patient();
patient.addIdentifier("urn:system", "001");
patient.addName().addFamily("Tester_testDelete").addGiven("Joe");
id1 = ourPatientDao.create(patient).getId();
}
{
Patient patient = new Patient();
patient.addIdentifier("urn:system", "002");
patient.addName().addFamily("Tester_testDelete").addGiven("John");
id2 = ourPatientDao.create(patient).getId();
}
{
Patient patient = ourPatientDao.read(id2);
patient.addIdentifier("ZZZZZZZ", "ZZZZZZZZZ");
id2b = ourPatientDao.update(patient, id2).getId();
}
ourLog.info("ID1:{} ID2:{} ID2b:{}", new Object[] { id1, id2, id2b });
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
params.put(Patient.SP_FAMILY, new StringDt("Tester_testDelete"));
List<Patient> patients = toList(ourPatientDao.search(params));
assertEquals(2, patients.size());
ourPatientDao.delete(id1);
patients = toList(ourPatientDao.search(params));
assertEquals(1, patients.size());
ourPatientDao.read(id1);
try {
ourPatientDao.read(id1.toVersionless());
fail();
} catch (ResourceGoneException e) {
// good
}
IBundleProvider history = ourPatientDao.history(null);
assertEquals(4 + initialHistory, history.size());
List<IResource> resources = history.getResources(0, 4);
assertNotNull(resources.get(0).getResourceMetadata().get(ResourceMetadataKeyEnum.DELETED_AT));
try {
ourPatientDao.delete(id2);
fail();
} catch (InvalidRequestException e) {
// good
}
ourPatientDao.delete(id2.toVersionless());
patients = toList(ourPatientDao.search(params));
assertEquals(0, patients.size());
}
@Test
public void testSearchWithIncludes() {
{
Organization org = new Organization();
org.getName().setValue("testSearchWithIncludes_O1");
IdDt orgId = ourOrganizationDao.create(org).getId();
Patient patient = new Patient();
patient.addIdentifier("urn:system", "001");
patient.addName().addFamily("Tester_testSearchWithIncludes_P1").addGiven("Joe");
@ -473,8 +554,7 @@ public class FhirResourceDaoTest {
assertEquals(1, patients.size());
}
@Test
public void testDatePeriodParamStartOnly() {
{
@ -509,7 +589,7 @@ public class FhirResourceDaoTest {
assertEquals(0, encs.size());
params = new SearchParameterMap();
params.add(Encounter.SP_DATE, new DateRangeParam("2001-01-03",null));
params.add(Encounter.SP_DATE, new DateRangeParam("2001-01-03", null));
params.add(Encounter.SP_IDENTIFIER, new IdentifierDt("testDatePeriodParam", "01"));
encs = toList(ourEncounterDao.search(params));
assertEquals(0, encs.size());
@ -550,14 +630,13 @@ public class FhirResourceDaoTest {
assertEquals(0, encs.size());
params = new SearchParameterMap();
params.add(Encounter.SP_DATE, new DateRangeParam( "2001-01-03",null));
params.add(Encounter.SP_DATE, new DateRangeParam("2001-01-03", null));
params.add(Encounter.SP_IDENTIFIER, new IdentifierDt("testDatePeriodParam", "02"));
encs = toList(ourEncounterDao.search(params));
assertEquals(0, encs.size());
}
@SuppressWarnings("unchecked")
private <T extends IResource> List<T> toList(IBundleProvider theSearch) {
return (List<T>) theSearch.getResources(0, theSearch.size());
@ -579,10 +658,10 @@ public class FhirResourceDaoTest {
List<Encounter> encs = toList(ourEncounterDao.search(params));
assertEquals(1, encs.size());
params = new SearchParameterMap();
params = new SearchParameterMap();
params.add(Encounter.SP_DATE, new DateRangeParam("2001-01-02", "2001-01-06"));
params.add(Encounter.SP_IDENTIFIER, new IdentifierDt("testDatePeriodParam", "03"));
encs = toList(ourEncounterDao.search(params));
encs = toList(ourEncounterDao.search(params));
assertEquals(1, encs.size());
params = new SearchParameterMap();
@ -610,14 +689,13 @@ public class FhirResourceDaoTest {
assertEquals(0, encs.size());
params = new SearchParameterMap();
params.add(Encounter.SP_DATE, new DateRangeParam( "2001-01-05",null));
params.add(Encounter.SP_DATE, new DateRangeParam("2001-01-05", null));
params.add(Encounter.SP_IDENTIFIER, new IdentifierDt("testDatePeriodParam", "03"));
encs = toList(ourEncounterDao.search(params));
assertEquals(0, encs.size());
}
@Test
public void testSearchStringParamWithNonNormalized() {
{
@ -694,7 +772,7 @@ public class FhirResourceDaoTest {
assertFalse(outcome.getId().isEmpty());
assertEquals("1", outcome.getId().getVersionIdPart());
Date now = new Date();
Patient retrieved = ourPatientDao.read(outcome.getId());
InstantDt published = (InstantDt) retrieved.getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED);
@ -730,20 +808,20 @@ public class FhirResourceDaoTest {
* Get history
*/
IBundleProvider historyBundle = ourPatientDao.history(outcome.getId(),null);
IBundleProvider historyBundle = ourPatientDao.history(outcome.getId(), null);
assertEquals(2, historyBundle.size());
List<IResource> history = historyBundle.getResources(0, 2);
assertEquals("1", history.get(1).getId().getVersionIdPart());
assertEquals("2", history.get(0).getId().getVersionIdPart());
assertEquals(published, history.get(1).getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED));
assertEquals(published, history.get(1).getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED));
assertEquals(updated, history.get(1).getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
assertEquals("001", ((Patient)history.get(1)).getIdentifierFirstRep().getValue().getValue());
assertEquals("001", ((Patient) history.get(1)).getIdentifierFirstRep().getValue().getValue());
assertEquals(published2, history.get(0).getResourceMetadata().get(ResourceMetadataKeyEnum.PUBLISHED));
assertEquals(updated2, history.get(0).getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED));
assertEquals("002", ((Patient)history.get(0)).getIdentifierFirstRep().getValue().getValue());
assertEquals("002", ((Patient) history.get(0)).getIdentifierFirstRep().getValue().getValue());
}

View File

@ -58,7 +58,7 @@ public class FhirSystemDaoTest {
Patient patient = new Patient();
patient.addIdentifier("urn:system", "testHistory");
patient.addName().addFamily("Tester").addGiven("Joe");
IdDt pid = ourPatientDao.create(patient).getId();
IdDt pid = ourPatientDao.create(patient).getId().toVersionless();
Thread.sleep(10);
IdDt newpid = ourPatientDao.update(patient, pid).getId();
@ -76,7 +76,7 @@ public class FhirSystemDaoTest {
assertEquals(newpid3, res.get(0).getId());
assertEquals(newpid2, res.get(1).getId());
assertEquals(newpid, res.get(2).getId());
assertEquals(pid, res.get(3).getId());
assertEquals(pid.toUnqualifiedVersionless(), res.get(3).getId().toUnqualifiedVersionless());
Location loc = new Location();
loc.getAddress().addLine("AAA");

View File

@ -22,7 +22,7 @@
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>2.1.2.RELEASE</version>
<version>${thymeleaf-version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
@ -36,6 +36,18 @@
<version>${junit_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>${hamcrest_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>${derby_version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
@ -71,8 +83,6 @@
</dependencies>
<properties>
<junit_version>4.11</junit_version>
<jetty_version>9.1.1.v20140108</jetty_version>
</properties>
<build>

Some files were not shown because too many files have changed in this diff Show More