Merge remote-tracking branch 'remotes/origin/master' into ks-20191119-scheduler
This commit is contained in:
commit
8c4ffc024d
|
@ -13,19 +13,22 @@ pool:
|
|||
jobs:
|
||||
- job: Build
|
||||
timeoutInMinutes: 360
|
||||
container: maven:3-jdk-11
|
||||
steps:
|
||||
- task: CacheBeta@0
|
||||
inputs:
|
||||
key: maven
|
||||
path: $(MAVEN_CACHE_FOLDER)
|
||||
displayName: Cache Maven local repo
|
||||
- task: Maven@3
|
||||
env:
|
||||
JAVA_HOME_11_X64: /usr/local/openjdk-11
|
||||
inputs:
|
||||
goals: 'clean install'
|
||||
# These are Maven CLI options (and show up in the build logs) - "-nsu"=Don't update snapshots. We can remove this when Maven OSS is more healthy
|
||||
options: '-P ALLMODULES,JACOCO -nsu'
|
||||
options: '-P ALLMODULES,JACOCO,CI -nsu'
|
||||
# These are JVM options (and don't show up in the build logs)
|
||||
mavenOptions: '-Xmx2048m $(MAVEN_OPTS) -Dorg.slf4j.simpleLogger.showDateTime=true -Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss,SSS -Duser.timezone=America/Toronto'
|
||||
jdkVersionOption: 1.11
|
||||
- script: bash <(curl https://codecov.io/bash) -t $(CODECOV_TOKEN)
|
||||
displayName: 'codecov'
|
||||
- task: PublishCodeCoverageResults@1
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -20,6 +20,12 @@ package ca.uhn.fhir.context;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
import org.apache.commons.text.WordUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -27,18 +33,11 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.text.WordUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IDatatype;
|
||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||
|
||||
public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildDefinition {
|
||||
|
||||
private static final String VALUE_REFERENCE = "valueReference";
|
||||
private static final String VALUE_RESOURCE = "valueResource";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RuntimeChildUndeclaredExtensionDefinition.class);
|
||||
private Map<String, BaseRuntimeElementDefinition<?>> myAttributeNameToDefinition;
|
||||
private Map<Class<? extends IBase>, String> myDatatypeToAttributeName;
|
||||
private Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> myDatatypeToDefinition;
|
||||
|
@ -48,15 +47,13 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
}
|
||||
|
||||
private void addReferenceBinding(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions, String value) {
|
||||
List<Class<? extends IBaseResource>> types = new ArrayList<Class<? extends IBaseResource>>();
|
||||
types.add(IBaseResource.class);
|
||||
BaseRuntimeElementDefinition<?> def = findResourceReferenceDefinition(theClassToElementDefinitions);
|
||||
|
||||
myAttributeNameToDefinition.put(value, def);
|
||||
/*
|
||||
* Resource reference - The correct name is 'valueReference' in DSTU2 and 'valueResource' in DSTU1
|
||||
*/
|
||||
if (value != VALUE_RESOURCE) {
|
||||
if (!value.equals(VALUE_RESOURCE)) {
|
||||
myDatatypeToAttributeName.put(theContext.getVersion().getResourceReferenceType(), value);
|
||||
myDatatypeToDefinition.put(BaseResourceReferenceDt.class, def);
|
||||
myDatatypeToDefinition.put(theContext.getVersion().getResourceReferenceType(), def);
|
||||
|
@ -71,10 +68,9 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
public List<IBase> getValues(IBase theTarget) {
|
||||
ExtensionDt target = (ExtensionDt) theTarget;
|
||||
if (target.getValue() != null) {
|
||||
return Collections.singletonList((IBase) target.getValue());
|
||||
return Collections.singletonList(target.getValue());
|
||||
}
|
||||
ArrayList<IBase> retVal = new ArrayList<IBase>(target.getUndeclaredExtensions());
|
||||
return retVal;
|
||||
return new ArrayList<>(target.getUndeclaredExtensions());
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -116,22 +112,13 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
@Override
|
||||
public void addValue(IBase theTarget, IBase theValue) {
|
||||
ExtensionDt target = (ExtensionDt) theTarget;
|
||||
if (theValue instanceof IDatatype) {
|
||||
target.setValue((IDatatype) theTarget);
|
||||
} else {
|
||||
target.getUndeclaredExtensions().add((ExtensionDt) theValue);
|
||||
}
|
||||
target.setValue((IDatatype) theTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(IBase theTarget, IBase theValue) {
|
||||
ExtensionDt target = (ExtensionDt) theTarget;
|
||||
if (theValue instanceof IDatatype) {
|
||||
target.setValue((IDatatype) theTarget);
|
||||
} else {
|
||||
target.getUndeclaredExtensions().clear();
|
||||
target.getUndeclaredExtensions().add((ExtensionDt) theValue);
|
||||
}
|
||||
target.setValue((IDatatype) theTarget);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -146,8 +133,6 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
return false;
|
||||
}
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RuntimeChildUndeclaredExtensionDefinition.class);
|
||||
|
||||
@Override
|
||||
void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
|
||||
Map<String, BaseRuntimeElementDefinition<?>> datatypeAttributeNameToDefinition = new HashMap<>();
|
||||
|
@ -163,15 +148,15 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
if (isSpecialization) {
|
||||
ourLog.trace("Not adding specialization: {}", next.getImplementingClass());
|
||||
}
|
||||
|
||||
|
||||
if (!isSpecialization) {
|
||||
|
||||
|
||||
if (!next.isStandardType()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
String qualifiedName = next.getImplementingClass().getName();
|
||||
|
||||
|
||||
/*
|
||||
* We don't want user-defined custom datatypes ending up overriding the built in
|
||||
* types here. It would probably be better for there to be a way for
|
||||
|
@ -183,7 +168,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String attrName = createExtensionChildName(next);
|
||||
if (datatypeAttributeNameToDefinition.containsKey(attrName)) {
|
||||
BaseRuntimeElementDefinition<?> existing = datatypeAttributeNameToDefinition.get(attrName);
|
||||
|
@ -207,8 +192,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
}
|
||||
|
||||
public static String createExtensionChildName(BaseRuntimeElementDefinition<?> next) {
|
||||
String attrName = "value" + WordUtils.capitalize(next.getName());
|
||||
return attrName;
|
||||
return "value" + WordUtils.capitalize(next.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,10 +22,16 @@ package ca.uhn.fhir.parser;
|
|||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.api.IIdentifiableElement;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.util.BundleUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -35,7 +41,13 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
|||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -530,11 +542,6 @@ public abstract class BaseParser implements IParser {
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getOverrideResourceIdWithBundleEntryFullUrl() {
|
||||
return myOverrideResourceIdWithBundleEntryFullUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends IBaseResource>> getPreferTypes() {
|
||||
return myPreferTypes;
|
||||
|
@ -705,39 +712,38 @@ public abstract class BaseParser implements IParser {
|
|||
RuntimeResourceDefinition def = myContext.getResourceDefinition(retVal);
|
||||
if ("Bundle".equals(def.getName())) {
|
||||
|
||||
BaseRuntimeChildDefinition entryChild = def.getChildByName("entry");
|
||||
BaseRuntimeElementCompositeDefinition<?> entryDef = (BaseRuntimeElementCompositeDefinition<?>) entryChild.getChildByName("entry");
|
||||
List<IBase> entries = entryChild.getAccessor().getValues(retVal);
|
||||
if (entries != null) {
|
||||
for (IBase nextEntry : entries) {
|
||||
|
||||
/**
|
||||
* If Bundle.entry.fullUrl is populated, set the resource ID to that
|
||||
*/
|
||||
// TODO: should emit a warning and maybe notify the error handler if the resource ID doesn't match the
|
||||
// fullUrl idPart
|
||||
BaseRuntimeChildDefinition fullUrlChild = entryDef.getChildByName("fullUrl");
|
||||
if (fullUrlChild == null) {
|
||||
continue; // TODO: remove this once the data model in tinder plugin catches up to 1.2
|
||||
}
|
||||
if (isOverrideResourceIdWithBundleEntryFullUrl()) {
|
||||
List<IBase> fullUrl = fullUrlChild.getAccessor().getValues(nextEntry);
|
||||
if (fullUrl != null && !fullUrl.isEmpty()) {
|
||||
IPrimitiveType<?> value = (IPrimitiveType<?>) fullUrl.get(0);
|
||||
if (value.isEmpty() == false) {
|
||||
List<IBase> entryResources = entryDef.getChildByName("resource").getAccessor().getValues(nextEntry);
|
||||
if (entryResources != null && entryResources.size() > 0) {
|
||||
IBaseResource res = (IBaseResource) entryResources.get(0);
|
||||
String versionId = res.getIdElement().getVersionIdPart();
|
||||
res.setId(value.getValueAsString());
|
||||
if (isNotBlank(versionId) && res.getIdElement().hasVersionIdPart() == false) {
|
||||
res.setId(res.getIdElement().withVersion(versionId));
|
||||
if (isOverrideResourceIdWithBundleEntryFullUrl()) {
|
||||
BundleUtil.processEntries(myContext, (IBaseBundle) retVal, t -> {
|
||||
String fullUrl = t.getFullUrl();
|
||||
if (fullUrl != null) {
|
||||
IBaseResource resource = t.getResource();
|
||||
if (resource != null) {
|
||||
IIdType resourceId = resource.getIdElement();
|
||||
if (isBlank(resourceId.getValue())) {
|
||||
resourceId.setValue(fullUrl);
|
||||
} else {
|
||||
if (fullUrl.startsWith("urn:") && fullUrl.endsWith(":" + resourceId.getIdPart())) {
|
||||
resourceId.setValue(fullUrl);
|
||||
} else {
|
||||
IIdType fullUrlId = myContext.getVersion().newIdType();
|
||||
fullUrlId.setValue(fullUrl);
|
||||
if (myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3)) {
|
||||
IIdType newId = fullUrlId;
|
||||
if (!newId.hasVersionIdPart() && resourceId.hasVersionIdPart()) {
|
||||
newId = newId.withVersion(resourceId.getVersionIdPart());
|
||||
}
|
||||
resourceId.setValue(newId.getValue());
|
||||
} else if (StringUtils.equals(fullUrlId.getIdPart(), resourceId.getIdPart())) {
|
||||
if (fullUrlId.hasBaseUrl()) {
|
||||
IIdType newResourceId = resourceId.withServerBase(fullUrlId.getBaseUrl(), resourceId.getResourceType());
|
||||
resourceId.setValue(newResourceId.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,19 +92,6 @@ public interface IParser {
|
|||
*/
|
||||
Boolean getStripVersionsFromReferences();
|
||||
|
||||
/**
|
||||
* If set to <code>true</code> (which is the default), the Bundle.entry.fullUrl will override the Bundle.entry.resource's
|
||||
* resource id if the fullUrl is defined. This behavior happens when parsing the source data into a Bundle object. Set this
|
||||
* to <code>false</code> if this is not the desired behavior (e.g. the client code wishes to perform additional
|
||||
* validation checks between the fullUrl and the resource id).
|
||||
*
|
||||
* @return Returns the parser instance's configuration setting for overriding resource ids with Bundle.entry.fullUrl when
|
||||
* parsing the source data into a Bundle object. This method will return <code>null</code> if no value is set, in
|
||||
* which case the value from the {@link ParserOptions} will be used (default is <code>true</code>)
|
||||
* @see ParserOptions
|
||||
*/
|
||||
Boolean getOverrideResourceIdWithBundleEntryFullUrl();
|
||||
|
||||
/**
|
||||
* Is the parser in "summary mode"? See {@link #setSummaryMode(boolean)} for information
|
||||
*
|
||||
|
|
|
@ -19,22 +19,25 @@ package ca.uhn.fhir.rest.param;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.*;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
public class StringParam extends BaseParam implements IQueryParameterType {
|
||||
|
||||
private boolean myContains;
|
||||
private boolean myExact;
|
||||
private String myValue;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -72,6 +75,16 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return ParameterUtil.escape(myValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(myExact)
|
||||
.append(myContains)
|
||||
.append(myValue)
|
||||
.append(getMissing())
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_STRING_EXACT.equals(theQualifier)) {
|
||||
|
@ -106,7 +119,7 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
eb.append(myContains, other.myContains);
|
||||
eb.append(myValue, other.myValue);
|
||||
eb.append(getMissing(), other.getMissing());
|
||||
|
||||
|
||||
return eb.isEquals();
|
||||
}
|
||||
|
||||
|
@ -114,6 +127,11 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return myValue;
|
||||
}
|
||||
|
||||
public StringParam setValue(String theValue) {
|
||||
myValue = theValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
@ -129,14 +147,6 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return myContains;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return StringUtils.isEmpty(myValue);
|
||||
}
|
||||
|
||||
public boolean isExact() {
|
||||
return myExact;
|
||||
}
|
||||
|
||||
/**
|
||||
* String parameter modifier <code>:contains</code>
|
||||
*/
|
||||
|
@ -149,6 +159,14 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return StringUtils.isEmpty(myValue);
|
||||
}
|
||||
|
||||
public boolean isExact() {
|
||||
return myExact;
|
||||
}
|
||||
|
||||
public StringParam setExact(boolean theExact) {
|
||||
myExact = theExact;
|
||||
if (myExact) {
|
||||
|
@ -158,11 +176,6 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return this;
|
||||
}
|
||||
|
||||
public StringParam setValue(String theValue) {
|
||||
myValue = theValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
|
|
@ -168,6 +168,8 @@ public class BundleUtil {
|
|||
|
||||
BaseRuntimeElementCompositeDefinition<?> entryChildContentsDef = (BaseRuntimeElementCompositeDefinition<?>) entryChildDef.getChildByName("entry");
|
||||
|
||||
BaseRuntimeChildDefinition fullUrlChildDef = entryChildContentsDef.getChildByName("fullUrl");
|
||||
|
||||
BaseRuntimeChildDefinition resourceChildDef = entryChildContentsDef.getChildByName("resource");
|
||||
BaseRuntimeChildDefinition requestChildDef = entryChildContentsDef.getChildByName("request");
|
||||
BaseRuntimeElementCompositeDefinition<?> requestChildContentsDef = (BaseRuntimeElementCompositeDefinition<?>) requestChildDef.getChildByName("request");
|
||||
|
@ -180,6 +182,11 @@ public class BundleUtil {
|
|||
String url = null;
|
||||
RequestTypeEnum requestType = null;
|
||||
String conditionalUrl = null;
|
||||
String fullUrl = fullUrlChildDef
|
||||
.getAccessor()
|
||||
.getFirstValueOrNull(nextEntry)
|
||||
.map(t->((IPrimitiveType<?>)t).getValueAsString())
|
||||
.orElse(null);
|
||||
|
||||
for (IBase nextResource : resourceChildDef.getAccessor().getValues(nextEntry)) {
|
||||
resource = (IBaseResource) nextResource;
|
||||
|
@ -217,7 +224,7 @@ public class BundleUtil {
|
|||
* order in the original bundle.
|
||||
*/
|
||||
BundleEntryMutator mutator = new BundleEntryMutator(nextEntry, requestChildDef, requestChildContentsDef);
|
||||
ModifiableBundleEntry entry = new ModifiableBundleEntry(new BundleEntryParts(requestType, url, resource, conditionalUrl), mutator);
|
||||
ModifiableBundleEntry entry = new ModifiableBundleEntry(new BundleEntryParts(fullUrl, requestType, url, resource, conditionalUrl), mutator);
|
||||
theProcessor.accept(entry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,15 +28,21 @@ public class BundleEntryParts {
|
|||
private final IBaseResource myResource;
|
||||
private final String myUrl;
|
||||
private final String myConditionalUrl;
|
||||
private final String myFullUrl;
|
||||
|
||||
public BundleEntryParts(RequestTypeEnum theRequestType, String theUrl, IBaseResource theResource, String theConditionalUrl) {
|
||||
public BundleEntryParts(String theFullUrl, RequestTypeEnum theRequestType, String theUrl, IBaseResource theResource, String theConditionalUrl) {
|
||||
super();
|
||||
myFullUrl = theFullUrl;
|
||||
myRequestType = theRequestType;
|
||||
myUrl = theUrl;
|
||||
myResource = theResource;
|
||||
myConditionalUrl = theConditionalUrl;
|
||||
}
|
||||
|
||||
public String getFullUrl() {
|
||||
return myFullUrl;
|
||||
}
|
||||
|
||||
public RequestTypeEnum getRequestType() {
|
||||
return myRequestType;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.util.bundle;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
public class ModifiableBundleEntry {
|
||||
private final BundleEntryParts myBundleEntryParts;
|
||||
|
@ -39,7 +40,15 @@ public class ModifiableBundleEntry {
|
|||
myBundleEntryMutator.setRequestUrl(theFhirContext, theRequestUrl);
|
||||
}
|
||||
|
||||
public String getFullUrl() {
|
||||
return myBundleEntryParts.getFullUrl();
|
||||
}
|
||||
|
||||
public String getRequestUrl() {
|
||||
return myBundleEntryParts.getUrl();
|
||||
}
|
||||
|
||||
public IBaseResource getResource() {
|
||||
return myBundleEntryParts.getResource();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -44,7 +44,7 @@ class ConditionalParamBinder implements IParameter {
|
|||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
if (theOuterCollectionType != null || theInnerCollectionType != null || theParameterType.equals(String.class) == false) {
|
||||
throw new ConfigurationException("Parameters annotated with @" + ConditionalUrlParam.class.getSimpleName() + " must be of type String, found incorrect parameteter in method \"" + theMethod + "\"");
|
||||
throw new ConfigurationException("Parameters annotated with @" + ConditionalUrlParam.class.getSimpleName() + " must be of type String, found incorrect parameter in method \"" + theMethod + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -208,23 +208,10 @@ public class MethodUtil {
|
|||
return b;
|
||||
}
|
||||
|
||||
public static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
|
||||
for (Annotation annotation : theAnnotations) {
|
||||
if (annotation instanceof Description) {
|
||||
Description desc = (Description) annotation;
|
||||
if (isNotBlank(desc.formalDefinition())) {
|
||||
theParameter.setDescription(desc.formalDefinition());
|
||||
} else {
|
||||
theParameter.setDescription(desc.shortDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<IParameter> getResourceParameters(final FhirContext theContext, Method theMethod,
|
||||
Object theProvider, RestOperationTypeEnum theRestfulOperationTypeEnum) {
|
||||
List<IParameter> parameters = new ArrayList<IParameter>();
|
||||
List<IParameter> parameters = new ArrayList<>();
|
||||
|
||||
Class<?>[] parameterTypes = theMethod.getParameterTypes();
|
||||
int paramIndex = 0;
|
||||
|
@ -271,7 +258,6 @@ public class MethodUtil {
|
|||
parameter.setChainlists(((RequiredParam) nextAnnotation).chainWhitelist(),
|
||||
((RequiredParam) nextAnnotation).chainBlacklist());
|
||||
parameter.setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
||||
MethodUtil.extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
} else if (nextAnnotation instanceof OptionalParam) {
|
||||
SearchParameter parameter = new SearchParameter();
|
||||
|
@ -282,7 +268,6 @@ public class MethodUtil {
|
|||
parameter.setChainlists(((OptionalParam) nextAnnotation).chainWhitelist(),
|
||||
((OptionalParam) nextAnnotation).chainBlacklist());
|
||||
parameter.setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
||||
MethodUtil.extractDescription(parameter, annotations);
|
||||
param = parameter;
|
||||
} else if (nextAnnotation instanceof RawParam) {
|
||||
param = new RawParamsParmeter();
|
||||
|
|
|
@ -165,6 +165,16 @@
|
|||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<includeDependencySources>true</includeDependencySources>
|
||||
<dependencySourceIncludes>
|
||||
<include>ca.uhn.hapi.fhir:org.hl7.fhir.convertors</include>
|
||||
</dependencySourceIncludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -104,6 +104,13 @@
|
|||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.basepom.maven</groupId>
|
||||
<artifactId>duplicate-finder-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Frequently Asked Questions
|
||||
|
||||
# Getting Help
|
||||
|
||||
### Where can I ask questions or get help?
|
||||
|
||||
Please see [this page](https://github.com/jamesagnew/hapi-fhir/wiki/Getting-Help) in the HAPI FHIR Wiki for information on getting help.
|
||||
|
||||
# Using HAPI FHIR
|
||||
|
||||
### What JDK version does HAPI support?
|
||||
|
||||
See the [HAPI FHIR Versions](/docs/introduction/versions.html) page for information on the current minimum Java version required in order to use HAPI FHIR.
|
||||
|
||||
# JPA Server
|
||||
|
||||
### I would like to connect to the Derby database using a JDBC database browser (e.g. Squirrel, Toad, DBVisualizer) so that I can access the underlying tables. How do I do that?
|
||||
|
||||
By default Derby doesn't actually open any TCP ports for you to connect externally to it. Being an embedded database, it works a bit differently than other databases in that the client actually is the database and there's no outside communication with it possible.
|
||||
|
||||
There are a few options available to work around this fact:
|
||||
|
||||
* The easiest thing is to just load your data using the FHIR API. E.g. you can use HTTP/REST creates, transactions, etc to load data into your database directly.
|
||||
|
||||
* If you want to access the underlying database, the next easiest thing is to configure the database to use a filesystem directory, e.g. `jdbc:derby:directory:target/jpaserver_derby_files;create=true`. You can then shut the server down and use that same URL to connect a derby client (e.g. Squirrel or DBVisualizer) to the same path. You may need to use a fully qualified path instead of a relative one though.
|
||||
|
||||
* Another option is to use a different database (e.g. MySQL, Postgres, Oracle, etc.). HAPI's JPA server is based on JPA/Hibernate so it will support any database platform that hibernate supports.
|
||||
|
||||
* A final option is to start up Derby in network mode. Doing this is a bit more involved since you need to start the derby server separately, and then use a special URL to connect to it.
|
||||
|
||||
# Contributing
|
||||
|
||||
### My build is failing with the following error: *[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test (default-test) on project hapi-fhir-jpaserver-base: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test failed: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?*
|
||||
|
||||
This typically means that your build is running out of memory. HAPI's unit tests execute by default in multiple threads (the thread count is determined by the number of CPU cores available) so in an environment with lots of cores but not enough RAM, you may run out. If you are getting this error, try executing the build with the following arguments:
|
||||
|
||||
```
|
||||
mvn -P ALLMODULES,NOPARALLEL install
|
||||
```
|
||||
|
||||
See [Hacking HAPI FHIR](/hacking.html) for more information on the build process.
|
|
@ -0,0 +1,116 @@
|
|||
# Hacking HAPI FHIR
|
||||
|
||||
This page contains useful information about how to get started in developing HAPI FHIR itself.
|
||||
|
||||
# Understanding the HAPI FHIR Codebase
|
||||
|
||||
The HAPI FHIR [Codebase](https://github.com/jamesagnew/hapi-fhir) has a number of subprojects. You will typically need to interact with several of them in order to develop HAPI, but you generally don't need all of them.
|
||||
|
||||
The following is a list of key subprojects you might open in your IDE:
|
||||
|
||||
* [hapi-fhir-base](https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-base): This is the core library, containing the parsers, client/server frameworks, and many other features. Note that this module does not contain any model classes (e.g. the Patient model class) as these are found in "structures" projects below.
|
||||
* hapi-fhir-structures-[version]: There are several structures projects (e.g. `hapi-fhir-structures-r4`), each of which contains model classes for a specific version of FHIR. Generally speaking you don't need to edit these project directly, as most (but not all) of their code is generated.
|
||||
* hapi-fhir-jpaserver-base: This module contains the JPA server.
|
||||
|
||||
# Getting the Sources
|
||||
|
||||
<p style="float:right;">
|
||||
<a class="externalLink" href="https://dev.azure.com/jamesagnew214/jamesagnew214/_build/latest?definitionId=1&branchName=master"><img src="https://dev.azure.com/jamesagnew214/jamesagnew214/_apis/build/status/jamesagnew.hapi-fhir?branchName=master" alt="Build Status" class="img-fluid"></a>
|
||||
</p>
|
||||
|
||||
The best way to grab our sources is with Git. Grab the repository URL from our [GitHub page](https://github.com/jamesagnew/hapi-fhir). We try our best to ensure that the sources are always left in a buildable state. Check Azure Pipelines CI (see the image/link on the right) to see if the sources currently build.
|
||||
|
||||
# Building HAPI FHIR
|
||||
|
||||
HAPI is built primary using [Apache Maven](http://maven.apache.org/). Even if you are using an IDE, you should **start by performing a command line build** before trying to get everything working in an IDE. This step ensures that generated code is available to the IDE.
|
||||
|
||||
Execute the build with the following command:
|
||||
|
||||
```
|
||||
mvn install
|
||||
```
|
||||
|
||||
Note that this complete build takes a long time because of all of the unit tests being executed. At the end you should expect to see a screen resembling:
|
||||
|
||||
```
|
||||
------------------------------------------------------------------------
|
||||
[INFO] Reactor Summary:
|
||||
[INFO]
|
||||
[INFO] HAPI-FHIR .......................................... SUCCESS [ 4.456 s]
|
||||
[INFO] HAPI FHIR - Deployable Artifact Parent POM ......... SUCCESS [ 2.841 s]
|
||||
[INFO] HAPI FHIR - Core Library ........................... SUCCESS [01:00 min]
|
||||
[INFO] HAPI Tinder Plugin ................................. SUCCESS [ 19.259 s]
|
||||
[INFO] HAPI FHIR Structures - DSTU1 (FHIR v0.80) .......... SUCCESS [01:40 min]
|
||||
[INFO] HAPI FHIR Structures - DSTU2 (FHIR v1.0.0) ......... SUCCESS [01:14 min]
|
||||
[INFO] HAPI FHIR Structures - DSTU3 ....................... SUCCESS [02:11 min]
|
||||
.... some lines removed .....
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] BUILD SUCCESS
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Total time: 20:45 min
|
||||
[INFO] Finished at: 2016-02-27T15:05:35+00:00
|
||||
```
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
If the build fails to execute successfully, try the following:
|
||||
|
||||
* The first thing to try is always a fresh clean build when things aren't working:
|
||||
|
||||
```
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
* **If you are trying to build a submodule** (e.g. `hapi-fhir-jpaserver-base`), try building the root project first. Especially when building from the Git <code>master</code>, often times there will be dependencies that require a fresh complete build (note that this is not generally an issue when building from a release version)
|
||||
|
||||
* If the build fails with memory issues (or mysteriously dies during unit tests), your build environment may be running out of memory. By default, the HAPI build executes unit tests in multiple parallel JVMs in order to save time. This can consume a lot of RAM and sometimes causes issues. Try executing with the following command to disable this behaviour:
|
||||
|
||||
```
|
||||
mvn -P ALLMODULES,NOPARALLEL install
|
||||
```
|
||||
|
||||
* If you figure something else out, please <b>let us know</b> so that we can add it to this list!
|
||||
|
||||
# Importing into Eclipse
|
||||
|
||||
This section shows how to import HAPI into Eclipse. There is no requirement to use Eclipse (IntelliJ/IDEA and Netbeans are both fine!) so feel free to skip this section.
|
||||
|
||||
**Maven Import**
|
||||
|
||||
Import the HAPI projects as Maven Modules by selecing **File -> Import...** from the File menu. Then select **Existing Module Projects** as shown below.
|
||||
|
||||
<img src="../../images/hacking_import.png"/>
|
||||
|
||||
**Select the Projects**
|
||||
|
||||
Next, browse to the directory where you checked out the HAPI FHIR sources. You might want to select only the projects you are interested in editing, in order to keep Eclipse's memory use down. You can always come back and import more later.
|
||||
|
||||
<img src="../../images/hacking_import_step2.png"/>
|
||||
|
||||
##
|
||||
<subsection name="Troubleshooting">
|
||||
|
||||
<p>
|
||||
When importing the HAPI projects into Eclipse, sometimes Eclipse
|
||||
will fail to correctly import libraries. If you import a module
|
||||
into Eclipse and it fails to compile with many errors relating to
|
||||
packages other than HAPI's, the following steps will fix this:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Delete the project from your Eclipse workspace</li>
|
||||
<li>
|
||||
On the local filesystem, delete the files <code>.project</code>
|
||||
and <code>.classpath</code>, and the directory <code>.settings</code>
|
||||
from each module you want to open.
|
||||
</li>
|
||||
<li>
|
||||
Import each module again using the instructions above
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
</body>
|
||||
|
||||
</document>
|
|
@ -2,6 +2,9 @@
|
|||
section.introduction.title=Welcome to HAPI FHIR
|
||||
page.introduction.table_of_contents=Table of Contents
|
||||
page.introduction.introduction=Introduction
|
||||
page.introduction.versions=FHIR and HAPI FHIR Versions
|
||||
page.introduction.modules=HAPI FHIR Modules
|
||||
page.introduction.downloading_and_importing=Downloading and Importing
|
||||
|
||||
section.model.title=Working With The FHIR Model
|
||||
page.model.working_with_resources=Working With Resources
|
||||
|
@ -28,6 +31,10 @@ page.android.client=Android Client
|
|||
section.tools.title=Tools
|
||||
page.tools.hapi_fhir_cli=Command Line Interface (CLI) Tool
|
||||
|
||||
section.contributing.title=Contributing to HAPI FHIR
|
||||
page.contributing.hacking_guide=Hacking Guide
|
||||
|
||||
section.appendix.title=Appendix
|
||||
page.appendix.logging=Logging
|
||||
page.appendix.changelog=Changelog
|
||||
page.appendix.faq=FAQ
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
# Downloading/Importing HAPI FHIR
|
||||
|
||||
If you are developing applications in Java, the easiest way to use HAPI FHIR is to use a build system which handles dependency management automatically. The two most common such systems are [Apache Maven](http://maven.apache.org) and [Gradle](https://gradle.org/). These systems will automatically download "dependency" libraries and add them to your classpath. If you are **not** using one of these systems, you can still manually download the latest release of HAPI by looking in the [GitHub Release Section](https://github.com/jamesagnew/hapi-fhir/releases).
|
||||
|
||||
|
||||
# Maven Users
|
||||
|
||||
To use HAPI in your application, at a minimum you need to include the HAPI-FHIR core JAR `hapi-fhir-base-[version].jar`, as well as at least one "structures" JAR.
|
||||
|
||||
The structures JAR contains classes with the resource and datatype definitions for a given version of FHIR.
|
||||
|
||||
If you are using Maven, the following example shows dependencies being added to include DSTU2 and R4 structures.
|
||||
|
||||
```xml
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-dstu2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-structures-r4</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
Note that if you wish to perform validation, you may also want to include the "validation resources" JARs, which contain schemas, profiles, and other artifacts used by the validator for your given version.
|
||||
|
||||
```xml
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-validation-resources-R4</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
# Gradle Users
|
||||
|
||||
If you are using Gradle, you may use the following dependencies. Note that if you are doing Android development, you may want to use our [Android build](/docs/android/client.html) instead.
|
||||
|
||||
```groovy
|
||||
compile 'ca.uhn.hapi.fhir:hapi-fhir-base:${project.version}'
|
||||
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2:${project.version}'
|
||||
compile 'ca.uhn.hapi.fhir:hapi-fhir-structures-r4:${project.version}'
|
||||
```
|
||||
|
||||
# Snapshot Builds
|
||||
|
||||
The HAPI FHIR project generally releases a new full software release 4 times per year, or approximately every 3 months.
|
||||
|
||||
Generally speaking it is a good idea to use a stable build. However, FHIR is a fast moving specification, and there is a lot of ongoing work in HAPI as well. There may be times when you want to try out the latest unreleased version, either to test a new feature or to get a bugfix. You can ususally look at the [Changelog](/docs/introduction/changelog.html) to get a sense of what has changed in the next unreleased version.
|
||||
|
||||
## Using Snapshot Builds
|
||||
|
||||
Snapshot builds of HAPI are pre-release builds which can contain fixes and new features not yet released in a formal release. To use snapshot builds of HAPI you may need to add a reference to the OSS snapshot repository to your project build file.
|
||||
|
||||
Using a snapshot build generally involves appending *-SNAPSHOT* to the version number, e.g. `4.1.0-SNAPSHOT`. In order to automatically download snapshot builds, you may also need to add a snapshot repository to your build file as shown below:
|
||||
|
||||
### Using Maven:
|
||||
|
||||
To use a snapshot build, you
|
||||
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>oss-snapshots</id>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
```
|
||||
|
||||
### Using Gradle:
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://oss.sonatype.org/content/repositories/snapshots"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Dependencies
|
||||
|
||||
The HAPI-FHIR library depends on other libraries to provide specific functionality. Some of those libraries are listed here:
|
||||
|
||||
## Logging (SLF4j, Logback, etc.)
|
||||
|
||||
HAPI requires SLF4j for logging support, and it is recommended to include an underlying logging framework such as Logback. See the [logging documentation](/docs/appendix/logging.html) for more information.
|
||||
|
||||
## StAX / Woodstox
|
||||
|
||||
XML processing (for resource marshalling and unmarshalling) uses the Java StAX API, which is a fast and efficient API for XML processing. HAPI bundles (for release archives) and depends on (for Maven builds) the [Woodstox](http://woodstox.codehaus.org/) library, which is a good implementation of StAX.
|
||||
|
||||
Upon starting up, HAPI will emit a log line indicating which StAX implementation is being used, e.g:
|
||||
|
||||
```
|
||||
08:01:32.044 [main] INFO ca.uhn.fhir.util.XmlUtil - FHIR XML procesing will use StAX implementation 'Woodstox XML-phrocessor' version '4.4.0'
|
||||
```
|
||||
|
||||
Although most testing is done using the Woodstox implementation of StAX, it is not required and HAPI should work correctly with any compliant implementation of StAX.
|
||||
|
||||
You can force Woodstox in an environment where multiple StAX libraries are present by setting the following system properties:
|
||||
|
||||
```java
|
||||
System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory");
|
||||
System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory");
|
||||
System.setProperty("javax.xml.stream.XMLEventFactory", "com.ctc.wstx.stax.WstxEventFactory");
|
||||
```
|
||||
|
||||
## PH-Schematron
|
||||
|
||||
If you are using the [Schematron Validation](/docs/validation/schema.html) module, you will also need to include the Ph-Schematron library on your classpath. (Note that prior to HAPI FHIR 3.4.0 we used Phloc-Schamtron instead, but that library has been discontinued).
|
||||
|
||||
If you are using Maven, this library is not added by default (it is marked as an optional dependency) since not all applications need Schematron support. As a result you will need to manually add the following dependencies to your project pom.xml:
|
||||
|
||||
```xml
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
<artifactId>ph-schematron</artifactId>
|
||||
<version>${ph_schematron_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
<artifactId>ph-commons</artifactId>
|
||||
<version>${ph_commons_version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
# HAPI FHIR Modules
|
||||
|
||||
The following table shows the modules that make up the HAPI FHIR library.
|
||||
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="3" style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;">
|
||||
Core Libraries
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-base</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-base/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This is the core HAPI FHIR library and is always required in order to use
|
||||
the framework. It contains the context, parsers, and other support classes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">
|
||||
Structures
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu (retired)</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contained FHIR DSTU1 model classes. It was retired in HAPI FHIR 3.0.0.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu2</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-structures-dstu2/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains FHIR DSTU2 model classes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-hl7org-dstu2</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-structures-hl7org-dstu2/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains alternate FHIR DSTU2 model classes. The HAPI FHIR and FHIR "Java Reference
|
||||
Implementation"
|
||||
libraries were merged in 2015, and at the time there were two parallel sets of DSTU2 model
|
||||
classes. This set more closely resembles the model classes for DSTU3+ where the other set
|
||||
more closely resembles the original DSTU1 model classes. The two DSTU2 model JARs are functionally
|
||||
identital, but the various utility methods on the classes are somewhat different.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-dstu3</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-structures-dstu3/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains FHIR DSTU3 model classes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r4</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-structures-r4/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains FHIR R4 model classes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-structures-r5</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-structures-r5/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains FHIR R5 model classes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-converter</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-converter/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains converters for converting between FHIR versions.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">Client
|
||||
Framework
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-client</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-client/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the core FHIR client framework, including an
|
||||
HTTP implementation based on
|
||||
<a href="https://hc.apache.org/">Apache HttpClient</a>. It is required in order
|
||||
to use client functionality in HAPI.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-client-okhttp</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains an alternate HTTP implementation based on
|
||||
<a href="http://square.github.io/okhttp/">OKHTTP</a>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-android</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the Android HAPI FHIR framework, which is a FHIR
|
||||
client framework which has been tailed specifically to run on Android.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">
|
||||
Validation
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the FHIR Profile Validator, which is used to
|
||||
validate resource instances against FHIR Profiles (StructureDefinitions,
|
||||
ValueSets, CodeSystems, etc.).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation-resources-dstu2</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the StructureDefinitions, ValueSets, CodeSystems, Schemas,
|
||||
and Schematrons for FHIR DSTU2
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation-resources-dstu2.1</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the StructureDefinitions, ValueSets, CodeSystems, Schemas,
|
||||
and Schematrons for FHIR DSTU2.1
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation-resources-dstu3</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the StructureDefinitions, ValueSets, CodeSystems, Schemas,
|
||||
and Schematrons for FHIR DSTU3
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation-resources-r4</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the StructureDefinitions, ValueSets, CodeSystems, Schemas,
|
||||
and Schematrons for FHIR R4
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-validation-resources-r5</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the StructureDefinitions, ValueSets, CodeSystems for R5. As of FHIR
|
||||
R5, Schema and Schematron files are no longer distributed with HAPI FHIR.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center; font-size: 1.2em; background: #DDE; padding: 3px;" colspan="3">Server</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-server</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-server/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the HAPI FHIR Server framework, which can be used to
|
||||
develop FHIR compliant servers against your own data storage layer.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-jpaserver-base</td>
|
||||
<td>
|
||||
<a href="../../apidocs/hapi-fhir-jpaserver-base/">JavaDoc</a>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the HAPI FHIR "JPA Server", which is a complete
|
||||
FHIR server solution including a database and implementations of many
|
||||
advanced FHIR server features.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="font-weight: bold; white-space: nowrap;">hapi-fhir-testpage-overlay</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
This module contains the web based "testpage overlay", which is the
|
||||
UI that powers our
|
||||
<a href="http://fhirtest.uhn.ca">Public Demo Server</a>
|
||||
and can also be added to your applications.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
# FHIR and HAPI FHIR Versions
|
||||
|
||||
The following table shows the various versions of the HAPI FHIR library, and the versions of the FHIR standard that they support. Note that support for stable releases of FHIR are shown in <span style="background: #CEC; padding: 3px;">GREEN</span> and support for draft pre-release versions of FHIR are shown in <span style="background: #EEB; padding: 3px;">YELLOW</span>.
|
||||
|
||||
Note also that after the release of the FHIR DSTU2 specification, the FHIR
|
||||
standard itself stopped using the DSTUx naming scheme, in favour or naming new releases STUx or simply Rx. Because HAPI FHIR already had draft support for what was then called DSTU3 at this time, we did not update our naming conventions until R4 in order to avoid breaking existing users' code. From the perspective of a user of HAPI FHIR, consider the terms DSTU3 / STU3 / R3 to be interchangeable.
|
||||
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>HAPI Version</b></td>
|
||||
<td><b>Min JDK</b></td>
|
||||
<td><b>DSTU1</b></td>
|
||||
<td><b>DSTU2</b></td>
|
||||
<td><b>DSTU2.1</b></td>
|
||||
<td><b>DSTU3</b></td>
|
||||
<td><b>R4</b></td>
|
||||
<td><b>R5</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>HAPI FHIR 1.1</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #EEB;">0.5.0<span class="download-version-hash">-5843</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 1.2</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #EEB;">0.5.0<span class="download-version-hash">-5843</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 1.3</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 1.4</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #EEB;">1.3.0<span class="download-version-hash">-7602</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 1.5</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #EEB;">1.4.0<span class="download-version-hash">-8138</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 1.6</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #EEB;">1.4.0<span class="download-version-hash">-8636</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 2.0</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #EEB;">1.6.0<span class="download-version-hash">-9663</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 2.1</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #EEB;">1.7.0<span class="download-version-hash">-10129</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 2.2</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #EEB;">1.8.0<span class="download-version-hash">-10528</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 2.3</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #EEB;">1.9.0<span class="download-version-hash">-11501</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 2.4</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 2.5</td>
|
||||
<td>JDK6</td>
|
||||
<td style="background: #CEC;">0.0.82</td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.0.0</td>
|
||||
<td>JDK7</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #EEB;">3.1.0<span class="download-version-hash">-12370</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.1.0</td>
|
||||
<td>JDK7</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #EEB;">3.1.0<span class="download-version-hash">-12370</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.2.0</td>
|
||||
<td>JDK7</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #EEB;">3.2.0<span class="download-version-hash">-12917</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.3.0</td>
|
||||
<td>JDK7</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #EEB;">3.2.0<span class="download-version-hash">-13271</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.4.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #EEB;">3.4.0<span class="download-version-hash">-13732</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.5.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #EEB;">3.4.0<span class="download-version-hash">-13732</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.6.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #EEB;">3.6.0<span class="download-version-hash">-1202b2eed0f</span></td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.7.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #CEC;">4.0.0</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 3.8.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #CEC;">4.0.0</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 4.0.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #CEC;">4.0.0</td>
|
||||
<td style="background: #EEB;">4.1.0<span class="download-version-hash">-e0e3caf9ba</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 4.1.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.2</td>
|
||||
<td style="background: #CEC;">4.0.1</td>
|
||||
<td style="background: #EEB;">4.1.0<span class="download-version-hash">-1a7623d866</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
|
@ -76,7 +76,7 @@ public class JaxRsRestfulClientFactory extends RestfulClientFactory {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
public synchronized IHttpClient getHttpClient(StringBuilder url, Map<String, List<String>> theIfNoneExistParams, String theIfNoneExistString, RequestTypeEnum theRequestType, List<Header> theHeaders) {
|
||||
Client client = getNativeClientClient();
|
||||
return new JaxRsHttpClient(client, url, theIfNoneExistParams, theIfNoneExistString, theRequestType, theHeaders);
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ public class JaxRsRestfulClientFactory extends RestfulClientFactory {
|
|||
|
||||
|
||||
@Override
|
||||
protected JaxRsHttpClient getHttpClient(String theServerBase) {
|
||||
protected synchronized JaxRsHttpClient getHttpClient(String theServerBase) {
|
||||
return new JaxRsHttpClient(getNativeClientClient(), new StringBuilder(theServerBase), null, null, null, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -691,7 +691,7 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<runOrder>alphabetical</runOrder>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx20484M -Xss128M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=2048M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
<forkCount>0.6C</forkCount>
|
||||
<excludes>*StressTest*</excludes>
|
||||
</configuration>
|
||||
|
|
|
@ -20,15 +20,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
|
@ -51,18 +43,8 @@ import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
|||
import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
|
||||
import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.jpa.util.BaseIterator;
|
||||
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
|
||||
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
|
||||
import ca.uhn.fhir.jpa.util.SqlQueryList;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.jpa.util.*;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
|
||||
|
@ -70,11 +52,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
||||
import ca.uhn.fhir.rest.api.SortSpec;
|
||||
import ca.uhn.fhir.rest.api.*;
|
||||
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.param.*;
|
||||
|
@ -85,6 +63,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
|||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
@ -119,11 +98,7 @@ import java.util.Map.Entry;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.trim;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
/**
|
||||
* The SearchBuilder is responsible for actually forming the SQL query that handles
|
||||
|
@ -2595,6 +2570,8 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
nextRoundMatches = pidsToInclude;
|
||||
} while (includes.size() > 0 && nextRoundMatches.size() > 0 && addedSomeThisRound);
|
||||
|
||||
allAdded.removeAll(original);
|
||||
|
||||
ourLog.info("Loaded {} {} in {} rounds and {} ms for search {}", allAdded.size(), theReverseMode ? "_revincludes" : "_includes", roundCounts, w.getMillisAndRestart(), theSearchIdOrDescription);
|
||||
|
||||
// Interceptor call: STORAGE_PREACCESS_RESOURCES
|
||||
|
@ -3109,19 +3086,26 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setParamsForUnitTest(SearchParameterMap theParams) {
|
||||
myParams = theParams;
|
||||
}
|
||||
|
||||
SearchParameterMap getParams() {
|
||||
return myParams;
|
||||
}
|
||||
|
||||
public class IncludesIterator extends BaseIterator<ResourcePersistentId> implements Iterator<ResourcePersistentId> {
|
||||
|
||||
private final RequestDetails myRequest;
|
||||
private Iterator<ResourcePersistentId> myCurrentIterator;
|
||||
private int myCurrentOffset;
|
||||
private ArrayList<ResourcePersistentId> myCurrentPids;
|
||||
private Set<ResourcePersistentId> myCurrentPids;
|
||||
private ResourcePersistentId myNext;
|
||||
private int myPageSize = myDaoConfig.getEverythingIncludesFetchPageSize();
|
||||
|
||||
IncludesIterator(Set<ResourcePersistentId> thePidSet, RequestDetails theRequest) {
|
||||
myCurrentPids = new ArrayList<>(thePidSet);
|
||||
myCurrentPids = new HashSet<>(thePidSet);
|
||||
myCurrentIterator = EMPTY_LONG_LIST.iterator();
|
||||
myCurrentOffset = 0;
|
||||
myRequest = theRequest;
|
||||
}
|
||||
|
||||
|
@ -3133,21 +3117,13 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
break;
|
||||
}
|
||||
|
||||
int start = myCurrentOffset;
|
||||
int end = myCurrentOffset + myPageSize;
|
||||
if (end > myCurrentPids.size()) {
|
||||
end = myCurrentPids.size();
|
||||
}
|
||||
if (end - start <= 0) {
|
||||
Set<Include> includes = Collections.singleton(new Include("*", true));
|
||||
Set<ResourcePersistentId> newPids = loadIncludes(myContext, myEntityManager, myCurrentPids, includes, false, getParams().getLastUpdated(), mySearchUuid, myRequest);
|
||||
if (newPids.isEmpty()) {
|
||||
myNext = NO_MORE;
|
||||
break;
|
||||
}
|
||||
myCurrentOffset = end;
|
||||
Collection<ResourcePersistentId> pidsToScan = myCurrentPids.subList(start, end);
|
||||
Set<Include> includes = Collections.singleton(new Include("*", true));
|
||||
Set<ResourcePersistentId> newPids = loadIncludes(myContext, myEntityManager, pidsToScan, includes, false, myParams.getLastUpdated(), mySearchUuid, myRequest);
|
||||
myCurrentIterator = newPids.iterator();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3484,4 +3460,8 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
return thePredicates.toArray(new Predicate[0]);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setEntityManagerForUnitTest(EntityManager theEntityManager) {
|
||||
myEntityManager = theEntityManager;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
|||
public static final int DEFAULT_SYNC_SIZE = 250;
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchCoordinatorSvcImpl.class);
|
||||
public static final String UNIT_TEST_CAPTURE_STACK = "unit_test_capture_stack";
|
||||
private final ConcurrentHashMap<String, SearchTask> myIdToSearchTask = new ConcurrentHashMap<>();
|
||||
@Autowired
|
||||
private FhirContext myContext;
|
||||
|
@ -902,6 +903,10 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
|||
failureCode = ((BaseServerResponseException) t).getStatusCode();
|
||||
}
|
||||
|
||||
if (System.getProperty(UNIT_TEST_CAPTURE_STACK) != null) {
|
||||
failureMessage += "\n" + ExceptionUtils.getStackTrace(rootCause);
|
||||
}
|
||||
|
||||
mySearch.setFailureMessage(failureMessage);
|
||||
mySearch.setFailureCode(failureCode);
|
||||
mySearch.setStatus(SearchStatusEnum.FAILED);
|
||||
|
|
|
@ -31,7 +31,7 @@ public interface IValueSetConceptAccumulator {
|
|||
|
||||
void includeConcept(String theSystem, String theCode, String theDisplay);
|
||||
|
||||
void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection<TermConceptDesignation> theDesignations);
|
||||
void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, @Nullable Collection<TermConceptDesignation> theDesignations);
|
||||
|
||||
void excludeConcept(String theSystem, String theCode);
|
||||
|
||||
|
|
|
@ -34,7 +34,9 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isAnyBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNoneBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ValueSetConceptAccumulator.class);
|
||||
|
@ -71,8 +73,10 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
@Override
|
||||
public void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection<TermConceptDesignation> theDesignations) {
|
||||
TermValueSetConcept concept = saveConcept(theSystem, theCode, theDisplay);
|
||||
for (TermConceptDesignation designation : theDesignations) {
|
||||
saveConceptDesignation(concept, designation);
|
||||
if (theDesignations != null) {
|
||||
for (TermConceptDesignation designation : theDesignations) {
|
||||
saveConceptDesignation(concept, designation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import ca.uhn.fhir.jpa.entity.TermConcept;
|
|||
import ca.uhn.fhir.jpa.term.IRecordHandler;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -37,7 +36,6 @@ public class LoincPartHandler implements IRecordHandler {
|
|||
|
||||
private final Map<String, TermConcept> myCode2Concept;
|
||||
private final TermCodeSystemVersion myCodeSystemVersion;
|
||||
private final Map<String, ValueSet> myIdToValueSet = new HashMap<>();
|
||||
private final Map<PartTypeAndPartName, String> myPartTypeAndPartNameToPartNumber = new HashMap<>();
|
||||
|
||||
public LoincPartHandler(TermCodeSystemVersion theCodeSystemVersion, Map<String, TermConcept> theCode2concept) {
|
||||
|
|
|
@ -1,25 +1,34 @@
|
|||
package ca.uhn.fhir.jpa.dao;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.TypedQuery;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SearchBuilderTest {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchBuilderTest.class);
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchBuilderTest.class);
|
||||
|
||||
@Test
|
||||
public void testCalculateMultiplierEqualNoDecimal() {
|
||||
|
@ -97,5 +106,32 @@ public class SearchBuilderTest {
|
|||
assertThat(out.toPlainString(), startsWith("20.000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncludeIterator() {
|
||||
BaseHapiFhirDao<?> mockDao = mock(BaseHapiFhirDao.class);
|
||||
when(mockDao.getConfig()).thenReturn(new DaoConfig());
|
||||
SearchBuilder searchBuilder = new SearchBuilder(mockDao);
|
||||
|
||||
searchBuilder.setParamsForUnitTest(new SearchParameterMap());
|
||||
EntityManager mockEntityManager = mock(EntityManager.class);
|
||||
searchBuilder.setEntityManagerForUnitTest(mockEntityManager);
|
||||
|
||||
Set<ResourcePersistentId> pidSet = new HashSet<>();
|
||||
pidSet.add(new ResourcePersistentId(1L));
|
||||
pidSet.add(new ResourcePersistentId(2L));
|
||||
|
||||
TypedQuery mockQuery = mock(TypedQuery.class);
|
||||
when(mockEntityManager.createQuery(any(), any())).thenReturn(mockQuery);
|
||||
List<ResourceLink> resultList = new ArrayList<>();
|
||||
ResourceLink link = new ResourceLink();
|
||||
ResourceTable target = new ResourceTable();
|
||||
target.setId(1L);
|
||||
link.setTargetResource(target);
|
||||
resultList.add(link);
|
||||
when(mockQuery.getResultList()).thenReturn(resultList);
|
||||
|
||||
SearchBuilder.IncludesIterator includesIterator = searchBuilder.new IncludesIterator(pidSet, null);
|
||||
// hasNext() should return false if the pid added was already on our list going in.
|
||||
assertFalse(includesIterator.hasNext());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.model.entity.*;
|
|||
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
|
||||
import ca.uhn.fhir.jpa.util.TestUtil;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
|
||||
|
@ -229,6 +230,36 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasChain() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setId("P");
|
||||
p.setActive(true);
|
||||
myPatientDao.update(p);
|
||||
|
||||
Group group = new Group();
|
||||
group.setId("G");
|
||||
group.addMember().getEntity().setReference("Patient/P");
|
||||
myGroupDao.update(group);
|
||||
|
||||
DiagnosticReport dr = new DiagnosticReport();
|
||||
dr.setId("DR");
|
||||
dr.getSubject().setReference("Patient/P");
|
||||
myDiagnosticReportDao.update(dr);
|
||||
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.setLoadSynchronous(true);
|
||||
|
||||
ReferenceParam referenceParam = new ReferenceParam();
|
||||
referenceParam.setValueAsQueryToken(myFhirCtx, "subject", "._has:Group:member:_id", "Group/G");
|
||||
map.add("subject", referenceParam);
|
||||
List<String> actual = toUnqualifiedVersionlessIdValues(myDiagnosticReportDao.search(map));
|
||||
assertThat(actual, containsInAnyOrder("DiagnosticReport/DR"));
|
||||
|
||||
// http://hapi.fhir.org/baseR4/DiagnosticReport?subject._has:Group:member:_id=52152
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Test
|
||||
public void testHasAndHas() {
|
||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao.r4;
|
|||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.entity.Search;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||
|
@ -2154,6 +2155,27 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchResourceLinkOnCanonical() {
|
||||
|
||||
Questionnaire q = new Questionnaire();
|
||||
q.setId("Q");
|
||||
myQuestionnaireDao.update(q);
|
||||
|
||||
QuestionnaireResponse qr = new QuestionnaireResponse();
|
||||
qr.setId("QR");
|
||||
qr.setQuestionnaire("Questionnaire/Q");
|
||||
String qrId = myQuestionnaireResponseDao.update(qr).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
List<QuestionnaireResponse> result = toList(myQuestionnaireResponseDao
|
||||
.search(new SearchParameterMap().setLoadSynchronous(true).add(QuestionnaireResponse.SP_QUESTIONNAIRE, new ReferenceParam("Questionnaire/Q"))));
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(qrId, result.get(0).getIdElement().toUnqualifiedVersionless().getValue());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchResourceLinkWithChain() {
|
||||
Patient patient = new Patient();
|
||||
|
|
|
@ -10,6 +10,8 @@ import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
|
|||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
|
||||
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
|
@ -116,6 +118,8 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
|||
private IResourceReindexingSvc myResourceReindexingSvc;
|
||||
@Autowired
|
||||
private IBulkDataExportSvc myBulkDataExportSvc;
|
||||
@Autowired
|
||||
private ITermReadSvc myTermSvc;
|
||||
|
||||
@Before
|
||||
@Transactional()
|
||||
|
@ -190,6 +194,36 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandValueSet() {
|
||||
CodeSystem cs = new CodeSystem();
|
||||
cs.setUrl("http://fooCS");
|
||||
cs.setContent(CodeSystem.CodeSystemContentMode.COMPLETE);
|
||||
cs.addConcept().setCode("CODEA");
|
||||
cs.addConcept().setCode("CODEB");
|
||||
myCodeSystemDao.create(cs);
|
||||
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl("http://fooVS");
|
||||
vs.getCompose()
|
||||
.addInclude()
|
||||
.setSystem("http://fooCS")
|
||||
.addConcept(new ValueSet.ConceptReferenceComponent().setCode("CODEA"));
|
||||
|
||||
// Explicit expand
|
||||
ValueSet outcome = myValueSetDao.expand(vs, null);
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
||||
assertEquals("CODEA", outcome.getExpansion().getContains().get(0).getCode());
|
||||
|
||||
// Deferred expand
|
||||
IIdType id = myValueSetDao.create(vs).getId().toUnqualifiedVersionless();
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
outcome = myValueSetDao.expand(id, null, mySrd);
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
||||
assertEquals("CODEA", outcome.getExpansion().getContains().get(0).getCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchByCodeIn() {
|
||||
CodeSystem cs = new CodeSystem();
|
||||
|
@ -207,6 +241,7 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest {
|
|||
.addConcept(new ValueSet.ConceptReferenceComponent().setCode("CODEA"));
|
||||
myValueSetDao.create(vs);
|
||||
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getCode().addCoding().setSystem("http://fooCS").setCode("CODEA");
|
||||
String obs1id = myObservationDao.create(obs).getId().toUnqualifiedVersionless().getValue();
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
|
@ -14,25 +13,31 @@ import org.hl7.fhir.dstu3.model.*;
|
|||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu3.model.Encounter.EncounterStatus;
|
||||
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||
import org.junit.*;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PatientEverythingDstu3Test.class);
|
||||
private String orgId;
|
||||
private String patId;
|
||||
private String myOrgId;
|
||||
private String myPatientId;
|
||||
private String encId1;
|
||||
private String encId2;
|
||||
private ArrayList<String> myObsIds;
|
||||
private String myWrongPatId;
|
||||
private String myWrongEnc1;
|
||||
private Organization myOrg;
|
||||
private Patient myPatient;
|
||||
|
||||
@Before
|
||||
public void beforeDisableResultReuse() {
|
||||
|
@ -54,42 +59,44 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
|
||||
|
||||
myDaoConfig.setAllowMultipleDelete(true);
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setName("an org");
|
||||
orgId = ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
ourLog.info("OrgId: {}", orgId);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
patId = ourClient.create().resource(patient).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
myOrg = new Organization();
|
||||
myOrg.setName("an org");
|
||||
myOrgId = ourClient.create().resource(myOrg).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
myOrg.setId(myOrgId);
|
||||
ourLog.info("OrgId: {}", myOrgId);
|
||||
|
||||
myPatient = new Patient();
|
||||
myPatient.getManagingOrganization().setReference(myOrgId);
|
||||
myPatientId = ourClient.create().resource(myPatient).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
myPatient.setId(myPatientId);
|
||||
|
||||
Patient patient2 = new Patient();
|
||||
patient2.getManagingOrganization().setReference(orgId);
|
||||
patient2.getManagingOrganization().setReference(myOrgId);
|
||||
myWrongPatId = ourClient.create().resource(patient2).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Encounter enc1 = new Encounter();
|
||||
enc1.setStatus(EncounterStatus.CANCELLED);
|
||||
enc1.getSubject().setReference(patId);
|
||||
enc1.getServiceProvider().setReference(orgId);
|
||||
enc1.getSubject().setReference(myPatientId);
|
||||
enc1.getServiceProvider().setReference(myOrgId);
|
||||
encId1 = ourClient.create().resource(enc1).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Encounter enc2 = new Encounter();
|
||||
enc2.setStatus(EncounterStatus.ARRIVED);
|
||||
enc2.getSubject().setReference(patId);
|
||||
enc2.getServiceProvider().setReference(orgId);
|
||||
enc2.getSubject().setReference(myPatientId);
|
||||
enc2.getServiceProvider().setReference(myOrgId);
|
||||
encId2 = ourClient.create().resource(enc2).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Encounter wrongEnc1 = new Encounter();
|
||||
wrongEnc1.setStatus(EncounterStatus.ARRIVED);
|
||||
wrongEnc1.getSubject().setReference(myWrongPatId);
|
||||
wrongEnc1.getServiceProvider().setReference(orgId);
|
||||
wrongEnc1.getServiceProvider().setReference(myOrgId);
|
||||
myWrongEnc1 = ourClient.create().resource(wrongEnc1).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
myObsIds = new ArrayList<String>();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
Observation obs = new Observation();
|
||||
obs.getSubject().setReference(patId);
|
||||
obs.getSubject().setReference(myPatientId);
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
String obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
myObsIds.add(obsId);
|
||||
|
@ -103,7 +110,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
@Test
|
||||
public void testEverythingReturnsCorrectResources() throws Exception {
|
||||
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
|
||||
|
||||
assertNull(bundle.getLink("next"));
|
||||
|
||||
|
@ -114,15 +121,51 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
ourLog.info("Found IDs: {}", actual);
|
||||
|
||||
assertThat(actual, hasItem(patId));
|
||||
assertThat(actual, hasItem(myPatientId));
|
||||
assertThat(actual, hasItem(encId1));
|
||||
assertThat(actual, hasItem(encId2));
|
||||
assertThat(actual, hasItem(orgId));
|
||||
assertThat(actual, hasItem(myOrgId));
|
||||
assertThat(actual, hasItems(myObsIds.toArray(new String[0])));
|
||||
assertThat(actual, not(hasItem(myWrongPatId)));
|
||||
assertThat(actual, not(hasItem(myWrongEnc1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEverythingHandlesCircularReferences() throws Exception {
|
||||
Patient linkedPatient1 = new Patient();
|
||||
linkedPatient1.addLink().setOther(new Reference(myPatientId));
|
||||
String linkedPatient1Id = ourClient.create().resource(linkedPatient1).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Patient linkedPatient2 = new Patient();
|
||||
linkedPatient2.addLink().setOther(new Reference(linkedPatient1Id));
|
||||
String linkedPatient2Id = ourClient.create().resource(linkedPatient2).execute().getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
myPatient.addLink().setOther(new Reference(linkedPatient2Id));
|
||||
ourClient.update().resource(myPatient).execute();
|
||||
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
|
||||
|
||||
assertNull(bundle.getLink("next"));
|
||||
|
||||
Set<String> actual = new TreeSet<String>();
|
||||
for (BundleEntryComponent nextEntry : bundle.getEntry()) {
|
||||
actual.add(nextEntry.getResource().getIdElement().toUnqualifiedVersionless().getValue());
|
||||
}
|
||||
|
||||
ourLog.info("Found IDs: {}", actual);
|
||||
|
||||
assertThat(actual, hasItem(myPatientId));
|
||||
assertThat(actual, hasItem(linkedPatient1Id));
|
||||
assertThat(actual, hasItem(linkedPatient2Id));
|
||||
assertThat(actual, hasItem(encId1));
|
||||
assertThat(actual, hasItem(encId2));
|
||||
assertThat(actual, hasItem(myOrgId));
|
||||
assertThat(actual, hasItems(myObsIds.toArray(new String[0])));
|
||||
assertThat(actual, not(hasItem(myWrongPatId)));
|
||||
assertThat(actual, not(hasItem(myWrongEnc1)));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #674
|
||||
*/
|
||||
|
@ -130,7 +173,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
public void testEverythingReturnsCorrectResourcesSmallPage() throws Exception {
|
||||
myDaoConfig.setEverythingIncludesFetchPageSize(1);
|
||||
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
|
||||
|
||||
assertNull(bundle.getLink("next"));
|
||||
|
||||
|
@ -141,10 +184,10 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
|
||||
ourLog.info("Found IDs: {}", actual);
|
||||
|
||||
assertThat(actual, hasItem(patId));
|
||||
assertThat(actual, hasItem(myPatientId));
|
||||
assertThat(actual, hasItem(encId1));
|
||||
assertThat(actual, hasItem(encId2));
|
||||
assertThat(actual, hasItem(orgId));
|
||||
assertThat(actual, hasItem(myOrgId));
|
||||
assertThat(actual, hasItems(myObsIds.toArray(new String[0])));
|
||||
assertThat(actual, not(hasItem(myWrongPatId)));
|
||||
assertThat(actual, not(hasItem(myWrongEnc1)));
|
||||
|
@ -156,7 +199,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
@Test
|
||||
public void testEverythingPagesWithCorrectEncodingJson() throws Exception {
|
||||
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=json&_count=1", EncodingEnum.JSON);
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=1", EncodingEnum.JSON);
|
||||
|
||||
assertNotNull(bundle.getLink("next").getUrl());
|
||||
assertThat(bundle.getLink("next").getUrl(), containsString("_format=json"));
|
||||
|
@ -173,7 +216,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
@Test
|
||||
public void testEverythingPagesWithCorrectEncodingXml() throws Exception {
|
||||
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=xml&_count=1", EncodingEnum.XML);
|
||||
Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=xml&_count=1", EncodingEnum.XML);
|
||||
|
||||
assertNotNull(bundle.getLink("next").getUrl());
|
||||
ourLog.info("Next link: {}", bundle.getLink("next").getUrl());
|
||||
|
|
|
@ -77,11 +77,14 @@ public class SearchCoordinatorSvcImplTest {
|
|||
|
||||
@After
|
||||
public void after() {
|
||||
System.clearProperty(SearchCoordinatorSvcImpl.UNIT_TEST_CAPTURE_STACK);
|
||||
verify(myCallingDao, atMost(myExpectedNumberOfSearchBuildersCreated)).newSearchBuilder();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
System.setProperty(SearchCoordinatorSvcImpl.UNIT_TEST_CAPTURE_STACK, "true");
|
||||
|
||||
myCurrentSearch = null;
|
||||
|
||||
mySvc = new SearchCoordinatorSvcImpl();
|
||||
|
@ -148,7 +151,8 @@ public class SearchCoordinatorSvcImplTest {
|
|||
try {
|
||||
result.getResources(0, 100000);
|
||||
} catch (InternalErrorException e) {
|
||||
assertEquals("FAILED", e.getMessage());
|
||||
assertThat(e.getMessage(), containsString("FAILED"));
|
||||
assertThat(e.getMessage(), containsString("at ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImplTest"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -187,9 +191,7 @@ public class SearchCoordinatorSvcImplTest {
|
|||
when(mySearchResultCacheSvc.fetchAllResultPids(any())).thenReturn(allResults);
|
||||
|
||||
when(mySearchCacheSvc.tryToMarkSearchAsInProgress(any())).thenAnswer(t->{
|
||||
Object argument = t.getArgument(0);
|
||||
Validate.isTrue( argument instanceof Search, "Argument is " + argument);
|
||||
Search search = (Search) argument;
|
||||
Search search = t.getArgument(0, Search.class);
|
||||
assertEquals(SearchStatusEnum.PASSCMPLET, search.getStatus());
|
||||
search.setStatus(SearchStatusEnum.LOADING);
|
||||
return Optional.of(search);
|
||||
|
@ -202,7 +204,7 @@ public class SearchCoordinatorSvcImplTest {
|
|||
List<IBaseResource> resources;
|
||||
|
||||
when(mySearchCacheSvc.save(any())).thenAnswer(t -> {
|
||||
Search search = (Search) t.getArguments()[0];
|
||||
Search search = t.getArgument(0, Search.class);
|
||||
myCurrentSearch = search;
|
||||
return search;
|
||||
});
|
||||
|
@ -328,7 +330,8 @@ public class SearchCoordinatorSvcImplTest {
|
|||
try {
|
||||
result.getResources(10, 20);
|
||||
} catch (InternalErrorException e) {
|
||||
assertEquals("Abort has been requested", e.getMessage());
|
||||
assertThat(e.getMessage(), containsString("Abort has been requested"));
|
||||
assertThat(e.getMessage(), containsString("at ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl"));
|
||||
}
|
||||
|
||||
completionLatch.await(10, TimeUnit.SECONDS);
|
||||
|
|
|
@ -2666,7 +2666,7 @@
|
|||
"fullUrl": "http://fhirtest.uhn.ca/baseDstu3/Practitioner/A45515",
|
||||
"resource": {
|
||||
"resourceType": "Practitioner",
|
||||
"id": "45515",
|
||||
"id": "A45515",
|
||||
"meta": {
|
||||
"versionId": "1",
|
||||
"lastUpdated": "2016-05-07T11:45:53.918-04:00"
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<runOrder>alphabetical</runOrder>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx20484M -Xss128M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=2048M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
<forkCount>0.6C</forkCount>
|
||||
<excludes>*StressTest*</excludes>
|
||||
</configuration>
|
||||
|
|
|
@ -23,6 +23,8 @@ package ca.uhn.fhir.jpa.searchparam;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.param.HasAndListParam;
|
||||
import ca.uhn.fhir.rest.param.HasParam;
|
||||
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenAndListParam;
|
||||
|
@ -61,6 +63,8 @@ public class ResourceMetaParams {
|
|||
resourceMetaAndParams.put(Constants.PARAM_PROFILE, UriAndListParam.class);
|
||||
resourceMetaParams.put(Constants.PARAM_SECURITY, TokenParam.class);
|
||||
resourceMetaAndParams.put(Constants.PARAM_SECURITY, TokenAndListParam.class);
|
||||
resourceMetaParams.put(Constants.PARAM_HAS, HasParam.class);
|
||||
resourceMetaAndParams.put(Constants.PARAM_HAS, HasAndListParam.class);
|
||||
RESOURCE_META_PARAMS = Collections.unmodifiableMap(resourceMetaParams);
|
||||
RESOURCE_META_AND_PARAMS = Collections.unmodifiableMap(resourceMetaAndParams);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.hl7.fhir.instance.model.api.IBaseReference;
|
|||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
|
@ -151,7 +152,31 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
|
||||
String nextType = toRootTypeName(value);
|
||||
switch (nextType) {
|
||||
case "uri":
|
||||
case "canonical":
|
||||
String typeName = toTypeName(value);
|
||||
|
||||
// Canonical has a root type of "uri"
|
||||
if ("canonical".equals(typeName)) {
|
||||
IPrimitiveType<?> valuePrimitive = (IPrimitiveType<?>) value;
|
||||
IBaseReference fakeReference = (IBaseReference) myContext.getElementDefinition("Reference").newInstance();
|
||||
fakeReference.setReference(valuePrimitive.getValueAsString());
|
||||
|
||||
/*
|
||||
* See #1583
|
||||
* Technically canonical fields should not allow local references (e.g.
|
||||
* Questionnaire/123) but it seems reasonable for us to interpret a canonical
|
||||
* containing a local reference for what it is, and allow people to seaerch
|
||||
* based on that.
|
||||
*/
|
||||
IIdType parsed = fakeReference.getReferenceElement();
|
||||
if (parsed.hasIdPart() && parsed.hasResourceType() && !parsed.isAbsolute()) {
|
||||
PathAndRef ref = new PathAndRef(searchParam.getName(), path, fakeReference);
|
||||
params.add(ref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
params.addWarning("Ignoring canonical reference (indexing canonical is not yet supported)");
|
||||
break;
|
||||
case "reference":
|
||||
|
@ -789,6 +814,11 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
return rootParentDefinition.getName();
|
||||
}
|
||||
|
||||
private String toTypeName(IBase nextObject) {
|
||||
BaseRuntimeElementDefinition<?> elementDefinition = getContext().getElementDefinition(nextObject.getClass());
|
||||
return elementDefinition.getName();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addDateTimeTypes(String theResourceType, Set<ResourceIndexedSearchParamDate> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
IPrimitiveType<Date> nextBaseDateTime = (IPrimitiveType<Date>) theValue;
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -47,7 +47,7 @@ class ConditionalParamBinder implements IParameter {
|
|||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
if (theOuterCollectionType != null || theInnerCollectionType != null || theParameterType.equals(String.class) == false) {
|
||||
throw new ConfigurationException(
|
||||
"Parameters annotated with @" + ConditionalUrlParam.class.getSimpleName() + " must be of type String, found incorrect parameteter in method \"" + theMethod + "\"");
|
||||
"Parameters annotated with @" + ConditionalUrlParam.class.getSimpleName() + " must be of type String, found incorrect parameter in method \"" + theMethod + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ import ca.uhn.fhir.parser.DataFormatException;
|
|||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
|
@ -91,6 +93,14 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
myDescription = null;
|
||||
}
|
||||
|
||||
for (Annotation[] nextParamAnnotations : theMethod.getParameterAnnotations()) {
|
||||
for (Annotation nextParam : nextParamAnnotations) {
|
||||
if (nextParam instanceof OptionalParam || nextParam instanceof RequiredParam) {
|
||||
throw new ConfigurationException("Illegal method parameter annotation @" + nextParam.annotationType().getSimpleName() + " on method: " + theMethod.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isBlank(theOperationName)) {
|
||||
throw new ConfigurationException("Method '" + theMethod.getName() + "' on type " + theMethod.getDeclaringClass().getName() + " is annotated with @" + Operation.class.getSimpleName()
|
||||
+ " but this annotation has no name defined");
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -270,7 +270,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -244,7 +244,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Dfile.encoding=UTF-8 -Xmx1024m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
@ -150,7 +150,7 @@
|
|||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -315,7 +315,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -174,6 +175,34 @@ public class JsonParserR4Test extends BaseTest {
|
|||
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">Copy © 1999</div>", p.getText().getDivAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeAndParseBundleWithFullUrlAndResourceIdMismatch() {
|
||||
|
||||
MessageHeader header = new MessageHeader();
|
||||
header.setId("1.1.1.1");
|
||||
header.setDefinition("Hello");
|
||||
|
||||
Bundle input = new Bundle();
|
||||
input
|
||||
.addEntry()
|
||||
.setFullUrl("urn:uuid:0.0.0.0")
|
||||
.setResource(header);
|
||||
|
||||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(input);
|
||||
|
||||
ourLog.info("Encoded: {}", encoded);
|
||||
assertThat(encoded, stringContainsInOrder(
|
||||
"\"fullUrl\": \"urn:uuid:0.0.0.0\"",
|
||||
"\"id\": \"1.1.1.1\""
|
||||
));
|
||||
|
||||
input = ourCtx.newJsonParser().parseResource(Bundle.class, encoded);
|
||||
assertEquals("urn:uuid:0.0.0.0", input.getEntry().get(0).getFullUrl());
|
||||
assertEquals("MessageHeader/1.1.1.1", input.getEntry().get(0).getResource().getId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeBinary() {
|
||||
Binary b = new Binary();
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Composition;
|
||||
import org.hl7.fhir.r4.model.MessageHeader;
|
||||
import org.hl7.fhir.r4.model.Narrative;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -41,5 +46,33 @@ public class XmlParserR4Test {
|
|||
int idx = encoded.indexOf(sectionText);
|
||||
assertNotEquals(-1, idx);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeAndParseBundleWithFullUrlAndResourceIdMismatch() {
|
||||
|
||||
MessageHeader header = new MessageHeader();
|
||||
header.setId("1.1.1.1");
|
||||
header.setDefinition("Hello");
|
||||
|
||||
Bundle input = new Bundle();
|
||||
input
|
||||
.addEntry()
|
||||
.setFullUrl("urn:uuid:0.0.0.0")
|
||||
.setResource(header);
|
||||
|
||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(input);
|
||||
|
||||
ourLog.info("Encoded: {}", encoded);
|
||||
assertThat(encoded, stringContainsInOrder(
|
||||
"<fullUrl value=\"urn:uuid:0.0.0.0\"/>",
|
||||
"<id value=\"1.1.1.1\"/>"
|
||||
));
|
||||
|
||||
input = ourCtx.newXmlParser().parseResource(Bundle.class, encoded);
|
||||
assertEquals("urn:uuid:0.0.0.0", input.getEntry().get(0).getFullUrl());
|
||||
assertEquals("MessageHeader/1.1.1.1", input.getEntry().get(0).getResource().getId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.rest.annotation.Elements;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
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.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.SummaryEnum;
|
||||
import ca.uhn.fhir.rest.client.apache.ApacheHttpRequest;
|
||||
import ca.uhn.fhir.rest.client.apache.ResourceEntity;
|
||||
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.client.api.IGenericClient;
|
||||
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
|
||||
|
@ -47,13 +54,24 @@ import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
|
|||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.either;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
@ -144,7 +162,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -173,7 +191,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 400, "foobar"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("foobar"), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("foobar"), StandardCharsets.UTF_8));
|
||||
|
||||
try {
|
||||
ourCtx.newRestfulClient(ITestClient.class, "http://foo").createPatient(patient);
|
||||
|
@ -197,7 +215,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
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(ourCtx.newXmlParser().encodeResourceToString(patient)), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(ourCtx.newXmlParser().encodeResourceToString(patient)), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -221,7 +239,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
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(resp), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(resp), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
MethodOutcome response = client.deletePatient(new IdType("1234"));
|
||||
|
@ -238,7 +256,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 204, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.deleteDiagnosticReport(new IdType("1234"));
|
||||
|
@ -259,7 +277,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
CapabilityStatement response = (CapabilityStatement) client.getServerConformanceStatement();
|
||||
|
@ -278,7 +296,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML_NEW + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryPatientInstance(new IdType("111"));
|
||||
|
@ -298,7 +316,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML_NEW + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryPatientType();
|
||||
|
@ -316,7 +334,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML_NEW + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.getHistoryServer();
|
||||
|
@ -340,7 +358,7 @@ public class ClientR4Test {
|
|||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
return new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -410,7 +428,7 @@ public class ClientR4Test {
|
|||
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
// Patient response = client.findPatientByMrn(new
|
||||
|
@ -422,7 +440,7 @@ public class ClientR4Test {
|
|||
|
||||
assertEquals("http://foo.com/Patient/123/_history/2333", response.getId());
|
||||
|
||||
InstantType lm = (InstantType) response.getMeta().getLastUpdatedElement();
|
||||
InstantType lm = response.getMeta().getLastUpdatedElement();
|
||||
lm.setTimeZoneZulu(true);
|
||||
assertEquals("1995-11-15T04:58:08.000Z", lm.getValueAsString());
|
||||
|
||||
|
@ -447,7 +465,7 @@ public class ClientR4Test {
|
|||
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "2011-01-02T22:01:02");
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("Internal Failure"), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("Internal Failure"), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
try {
|
||||
|
@ -474,7 +492,7 @@ public class ClientR4Test {
|
|||
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "2011-01-02T22:01:02");
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
try {
|
||||
|
@ -498,7 +516,7 @@ public class ClientR4Test {
|
|||
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "Wed, 15 Nov 1995 04:58:08 GMT");
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(headers);
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
// Patient response = client.findPatientByMrn(new
|
||||
|
@ -508,7 +526,7 @@ public class ClientR4Test {
|
|||
assertEquals("http://foo/Patient/111", capt.getValue().getURI().toString());
|
||||
assertEquals("PRP1660", response.getIdentifier().get(0).getValueElement().getValue());
|
||||
|
||||
InstantType lm = (InstantType) response.getMeta().getLastUpdatedElement();
|
||||
InstantType lm = response.getMeta().getLastUpdatedElement();
|
||||
lm.setTimeZoneZulu(true);
|
||||
assertEquals("1995-11-15T04:58:08.000Z", lm.getValueAsString());
|
||||
|
||||
|
@ -523,7 +541,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", "application/fhir+xml; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
// Patient response = client.findPatientByMrn(new
|
||||
|
@ -544,7 +562,7 @@ public class ClientR4Test {
|
|||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
||||
|
@ -572,7 +590,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
StringParam str = new StringParam("FOO$BAR");
|
||||
|
@ -592,7 +610,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
DateRangeParam param = new DateRangeParam();
|
||||
|
@ -613,7 +631,7 @@ public class ClientR4Test {
|
|||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
// httpResponse = new BasicHttpResponse(statusline, catalog, locale)
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
@ -635,7 +653,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Patient response = client.findPatientQuantity(new QuantityParam(ParamPrefixEnum.GREATERTHAN, 123L, "foo", "bar"));
|
||||
|
@ -654,7 +672,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Patient response = client.findPatientByMrn(new TokenParam("urn:foo", "123"));
|
||||
|
@ -673,7 +691,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientNoParams();
|
||||
|
@ -691,7 +709,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientOneParam(new StringParam("BB"));
|
||||
|
@ -709,7 +727,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
TokenOrListParam identifiers = new TokenOrListParam();
|
||||
|
@ -730,7 +748,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClientWithCustomType client = ourCtx.newRestfulClient(ITestClientWithCustomType.class, "http://foo");
|
||||
CustomPatient response = client.getPatientByDob(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, "2011-01-02"));
|
||||
|
@ -749,7 +767,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClientWithCustomTypeList client = ourCtx.newRestfulClient(ITestClientWithCustomTypeList.class, "http://foo");
|
||||
List<CustomPatient> response = client.getPatientByDob(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, "2011-01-02"));
|
||||
|
@ -771,7 +789,7 @@ public class ClientR4Test {
|
|||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
return new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -813,7 +831,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
StringAndListParam andListParam = new StringAndListParam();
|
||||
|
@ -837,7 +855,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
// TODO: document this
|
||||
|
||||
|
@ -845,13 +863,13 @@ public class ClientR4Test {
|
|||
client.getPatientByDob(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, "2011-01-02"));
|
||||
assertEquals("http://foo/Patient?birthdate=ge2011-01-02", capt.getAllValues().get(0).getURI().toString());
|
||||
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
client.setEncoding(EncodingEnum.JSON); // this needs to be actually
|
||||
// implemented
|
||||
client.getPatientByDob(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, "2011-01-02"));
|
||||
assertEquals("http://foo/Patient?birthdate=ge2011-01-02&_format=json", capt.getAllValues().get(1).getURI().toString());
|
||||
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
client.setPrettyPrint(true);
|
||||
client.getPatientByDob(new DateParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, "2011-01-02"));
|
||||
assertEquals("http://foo/Patient?birthdate=ge2011-01-02&_format=json&_pretty=true", capt.getAllValues().get(2).getURI().toString());
|
||||
|
@ -877,7 +895,7 @@ public class ClientR4Test {
|
|||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
// httpResponse = new BasicHttpResponse(statusline, catalog, locale)
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
|
@ -900,7 +918,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.setSummary(SummaryEnum.DATA);
|
||||
|
@ -919,10 +937,10 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
client.getPatientWithIncludes(new StringParam("aaa"), Arrays.asList(new Include[]{new Include("inc1"), new Include("inc2", true), new Include("inc3", true)}));
|
||||
client.getPatientWithIncludes(new StringParam("aaa"), Arrays.asList(new Include("inc1"), new Include("inc2", true), new Include("inc3", true)));
|
||||
|
||||
assertEquals("http://foo/Patient?withIncludes=aaa&_include=inc1&_include%3Aiterate=inc2&_include%3Aiterate=inc3", capt.getValue().getURI().toString());
|
||||
|
||||
|
@ -937,7 +955,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
Bundle response = client.findPatientByName(new StringParam("AAA"), null);
|
||||
|
@ -950,7 +968,7 @@ public class ClientR4Test {
|
|||
* Now with a first name
|
||||
*/
|
||||
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
response = client.findPatientByName(new StringParam("AAA"), new StringParam("BBB"));
|
||||
|
||||
|
@ -970,7 +988,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClientWithStringIncludes client = ourCtx.newRestfulClient(ITestClientWithStringIncludes.class, "http://foo");
|
||||
client.getPatientWithIncludes(new StringParam("aaa"), "inc1");
|
||||
|
@ -991,7 +1009,7 @@ public class ClientR4Test {
|
|||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8"));
|
||||
return new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1037,7 +1055,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -1065,7 +1083,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
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")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray(Constants.HEADER_LOCATION, "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -1088,7 +1106,7 @@ public class ClientR4Test {
|
|||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
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")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_409_CONFLICT, "Conflict"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -1105,7 +1123,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -1129,7 +1147,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), Constants.STATUS_HTTP_204_NO_CONTENT, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(""), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -1152,7 +1170,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(response), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(response), StandardCharsets.UTF_8));
|
||||
|
||||
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://testValidateServerBaseWithInvalidResponse");
|
||||
|
@ -1180,7 +1198,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_JSON_NEW + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(resp), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(resp), StandardCharsets.UTF_8));
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(toHeaderArray("Location", "http://example.com/fhir/Patient/100/_history/200"));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
|
@ -1215,7 +1233,7 @@ public class ClientR4Test {
|
|||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||
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(msg), Charset.forName("UTF-8")));
|
||||
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), StandardCharsets.UTF_8));
|
||||
|
||||
ITestClient client = ourCtx.newRestfulClient(ITestClient.class, "http://foo");
|
||||
// Patient response = client.findPatientByMrn(new
|
||||
|
@ -1227,6 +1245,67 @@ public class ClientR4Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientWithAndOrList() throws IOException {
|
||||
|
||||
Bundle response = new Bundle().setType(Bundle.BundleType.SEARCHSET);
|
||||
|
||||
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), 200, "OK"));
|
||||
when(myHttpResponse.getEntity()).thenReturn(new ResourceEntity(ourCtx, response));
|
||||
|
||||
ITestClientWithAndOr client = ourCtx.newRestfulClient(ITestClientWithAndOr.class, "http://foo");
|
||||
StringAndListParam andList = new StringAndListParam();
|
||||
StringOrListParam orListA = new StringOrListParam();
|
||||
orListA.add(new StringParam("A1"));
|
||||
orListA.add(new StringParam("A2"));
|
||||
andList.addAnd(orListA);
|
||||
StringOrListParam orListB = new StringOrListParam();
|
||||
orListB.add(new StringParam("B1"));
|
||||
orListB.add(new StringParam("B2"));
|
||||
andList.addAnd(orListB);
|
||||
client.search(andList);
|
||||
|
||||
assertEquals("http://foo/Patient?foo=A1%2CA2&foo=B1%2CB2", capt.getValue().getURI().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientWithAndOrList2() throws IOException {
|
||||
|
||||
Bundle response = new Bundle().setType(Bundle.BundleType.SEARCHSET);
|
||||
|
||||
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), 200, "OK"));
|
||||
when(myHttpResponse.getEntity()).thenReturn(new ResourceEntity(ourCtx, response));
|
||||
|
||||
try {
|
||||
ourCtx.newRestfulClient(ITestClientWithAndOr2.class, "http://foo");
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Argument #0 of Method 'search' in type 'ca.uhn.fhir.rest.client.ClientR4Test.ITestClientWithAndOr2' is of an invalid generic type (can not be a collection of a collection of a collection)", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientWithAndOrList3() throws IOException {
|
||||
|
||||
Bundle response = new Bundle().setType(Bundle.BundleType.SEARCHSET);
|
||||
|
||||
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), 200, "OK"));
|
||||
when(myHttpResponse.getEntity()).thenReturn(new ResourceEntity(ourCtx, response));
|
||||
|
||||
ITestClientWithAndOr3 client = ourCtx.newRestfulClient(ITestClientWithAndOr3.class, "http://foo");
|
||||
Set<Include> orListA = new HashSet<>();
|
||||
orListA.add(new Include("a"));
|
||||
orListA.add(new Include("b"));
|
||||
client.search(orListA);
|
||||
|
||||
assertEquals("http://foo/Patient?_include=a&_include=b", capt.getValue().getURI().toString());
|
||||
}
|
||||
|
||||
private Header[] toHeaderArray(String theName, String theValue) {
|
||||
return new Header[]{new BasicHeader(theName, theValue)};
|
||||
}
|
||||
|
@ -1245,40 +1324,61 @@ public class ClientR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
interface ITestClientWithAndOr extends IBasicClient {
|
||||
|
||||
@Search()
|
||||
List<Patient> search(@OptionalParam(name = "foo") StringAndListParam theParam);
|
||||
|
||||
}
|
||||
|
||||
interface ITestClientWithAndOr2 extends IBasicClient {
|
||||
|
||||
@Search()
|
||||
List<Patient> search(@OptionalParam(name = "foo") List<List<String>> theParam);
|
||||
|
||||
}
|
||||
|
||||
public interface ITestClientWithAndOr3 extends IBasicClient {
|
||||
|
||||
@Search()
|
||||
List<Patient> search(@IncludeParam Set<Include> theParam);
|
||||
|
||||
}
|
||||
|
||||
private interface ClientWithoutAnnotation extends IBasicClient {
|
||||
Patient read(@IdParam IdType theId);
|
||||
}
|
||||
|
||||
public interface ITestClientWithCustomType extends IBasicClient {
|
||||
@Search()
|
||||
public CustomPatient getPatientByDob(@RequiredParam(name = Patient.SP_BIRTHDATE) DateParam theBirthDate);
|
||||
CustomPatient getPatientByDob(@RequiredParam(name = Patient.SP_BIRTHDATE) DateParam theBirthDate);
|
||||
}
|
||||
|
||||
public interface ITestClientWithCustomTypeList extends IBasicClient {
|
||||
@Search()
|
||||
public List<CustomPatient> getPatientByDob(@RequiredParam(name = Patient.SP_BIRTHDATE) DateParam theBirthDate);
|
||||
List<CustomPatient> getPatientByDob(@RequiredParam(name = Patient.SP_BIRTHDATE) DateParam theBirthDate);
|
||||
}
|
||||
|
||||
public interface ITestClientWithElements extends IBasicClient {
|
||||
@Search()
|
||||
public List<Patient> getPatientWithIncludes(@Elements Set<String> theElements);
|
||||
List<Patient> getPatientWithIncludes(@Elements Set<String> theElements);
|
||||
|
||||
@Search()
|
||||
public List<Patient> getPatientWithIncludes(@Elements String theElements);
|
||||
List<Patient> getPatientWithIncludes(@Elements String theElements);
|
||||
|
||||
}
|
||||
|
||||
public interface ITestClientWithStringIncludes extends IBasicClient {
|
||||
@Search()
|
||||
public Patient getPatientWithIncludes(@RequiredParam(name = "withIncludes") StringParam theString, @IncludeParam String theInclude);
|
||||
Patient getPatientWithIncludes(@RequiredParam(name = "withIncludes") StringParam theString, @IncludeParam String theInclude);
|
||||
}
|
||||
|
||||
public interface ITestClientWithSummary extends IBasicClient {
|
||||
@Search()
|
||||
public List<Patient> getPatientWithIncludes(List<SummaryEnum> theSummary);
|
||||
List<Patient> getPatientWithIncludes(List<SummaryEnum> theSummary);
|
||||
|
||||
@Search()
|
||||
public List<Patient> getPatientWithIncludes(SummaryEnum theSummary);
|
||||
List<Patient> getPatientWithIncludes(SummaryEnum theSummary);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||
import ca.uhn.fhir.test.utilities.server.ResourceProviderRule;
|
||||
import ca.uhn.fhir.test.utilities.server.RestfulServerRule;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.InputStreamEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BlockingContentR4Test {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BlockingContentR4Test.class);
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
@ClassRule
|
||||
public static RestfulServerRule ourServerRule = new RestfulServerRule(ourCtx);
|
||||
@Rule
|
||||
public ResourceProviderRule myPatientProviderRule = new ResourceProviderRule(ourServerRule, new SystemProvider());
|
||||
|
||||
@Test
|
||||
public void testCreateWith100Continue() throws Exception {
|
||||
Patient patient = new Patient();
|
||||
patient.setActive(true);
|
||||
|
||||
Bundle input = new Bundle();
|
||||
input.setType(Bundle.BundleType.TRANSACTION);
|
||||
input.addEntry().setResource(patient).setFullUrl("Patient/").getRequest().setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(true).build();
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
builder.setDefaultRequestConfig(config);
|
||||
try (CloseableHttpClient client = builder.build()) {
|
||||
|
||||
String resourceAsString = ourCtx.newJsonParser().encodeResourceToString(input);
|
||||
|
||||
// InputStream inputStream = new BlockingInputStream(resourceAsString.getBytes(Charsets.UTF_8));
|
||||
byte[] bytes = resourceAsString.getBytes(Charsets.UTF_8);
|
||||
InputStream inputStream = new ByteArrayInputStream(bytes);
|
||||
HttpEntity entity = new InputStreamEntity(inputStream, ContentType.parse("application/fhir+json")){
|
||||
@Override
|
||||
public long getContentLength() {
|
||||
return bytes.length + 100;
|
||||
}
|
||||
};
|
||||
|
||||
HttpPost post = new HttpPost("http://localhost:" + ourServerRule.getPort() + "/");
|
||||
post.setEntity(entity);
|
||||
try (CloseableHttpResponse resp = client.execute(post)) {
|
||||
ourLog.info(Arrays.asList(resp.getAllHeaders()).toString().replace(", ", "\n"));
|
||||
ourLog.info(resp.toString());
|
||||
ourLog.info(IOUtils.toString(resp.getEntity().getContent(), Charsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static class BlockingInputStream extends InputStream {
|
||||
private final ByteArrayInputStream myWrap;
|
||||
private int myByteCount = 0;
|
||||
|
||||
public BlockingInputStream(byte[] theBytes) {
|
||||
myWrap = new ByteArrayInputStream(theBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (myByteCount++ == 10) {
|
||||
ourLog.info("About to block...");
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
} catch (InterruptedException e) {
|
||||
ourLog.warn("Interrupted", e);
|
||||
}
|
||||
}
|
||||
return myWrap.read();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SystemProvider {
|
||||
|
||||
@Transaction
|
||||
public Bundle transaction(@TransactionParam Bundle theInput) {
|
||||
return theInput;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +1,30 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
||||
import ca.uhn.fhir.rest.annotation.Operation;
|
||||
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
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.param.TokenParam;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
public class ServerInvalidDefinitionR4Test {
|
||||
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
import ca.uhn.fhir.rest.annotation.*;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class ServerInvalidDefinitionDstu2Test {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
|
||||
@Test
|
||||
public void testWrongConditionalUrlType() {
|
||||
|
@ -38,7 +38,7 @@ public class ServerInvalidDefinitionDstu2Test {
|
|||
} catch (ServletException e) {
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("ConfigurationException"));
|
||||
assertThat(e.getCause().toString(), StringContains.containsString(
|
||||
"Parameters annotated with @ConditionalUrlParam must be of type String, found incorrect parameteter in method \"public ca.uhn.fhir.rest.api.MethodOutcome ca.uhn.fhir.rest.server.ServerInvalidDefinitionDstu2Test$UpdateWithWrongConditionalUrlType.update(ca.uhn.fhir.rest.param.TokenParam,ca.uhn.fhir.model.dstu2.resource.Patient)"));
|
||||
"Parameters annotated with @ConditionalUrlParam must be of type String, found incorrect parameter in method \"public ca.uhn.fhir.rest.api.MethodOutcome ca.uhn.fhir.rest.server.ServerInvalidDefinitionR4Test$UpdateWithWrongConditionalUrlType.update(ca.uhn.fhir.rest.param.TokenParam,org.hl7.fhir.r4.model.Patient)"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class ServerInvalidDefinitionDstu2Test {
|
|||
} catch (ServletException e) {
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("ConfigurationException"));
|
||||
assertThat(e.getCause().toString(), StringContains
|
||||
.containsString("Method 'update' is annotated with @ResourceParam but has a type that is not an implemtation of org.hl7.fhir.instance.model.api.IBaseResource or String or byte[]"));
|
||||
.containsString("Method 'update' is annotated with @ResourceParam but has a type that is not an implemtation of org.hl7.fhir.instance.model.api.IBaseResource or String or byte[]"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,29 @@ public class ServerInvalidDefinitionDstu2Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongParameterAnnotationOnOperation() {
|
||||
class MyProvider {
|
||||
|
||||
@Operation(name = "foo")
|
||||
public MethodOutcome update(@OptionalParam(name = "foo") StringType theFoo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RestfulServer srv = new RestfulServer(ourCtx);
|
||||
srv.setFhirContext(ourCtx);
|
||||
srv.registerProvider(new MyProvider());
|
||||
|
||||
try {
|
||||
srv.init();
|
||||
fail();
|
||||
} catch (ServletException e) {
|
||||
assertThat(e.getCause().toString(), StringContains.containsString("Failure scanning class MyProvider: Illegal method parameter annotation @OptionalParam on method: public ca.uhn.fhir.rest.api.MethodOutcome ca.uhn.fhir.rest.server.ServerInvalidDefinitionR4Test$1MyProvider.update(org.hl7.fhir.r4.model.StringType)"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateWithWrongConditionalUrlType implements IResourceProvider {
|
||||
|
||||
@Override
|
||||
|
@ -144,4 +167,9 @@ public class ServerInvalidDefinitionDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
|
@ -40,18 +39,18 @@ import org.junit.Before;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.rest.annotation.Create;
|
||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
||||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.client.MyPatientWithExtensions;
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class ServerMimetypeR4Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerMimetypeR4Test.class);
|
||||
|
@ -406,45 +405,16 @@ public class ServerMimetypeR4Test {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() throws Exception {
|
||||
JettyUtil.closeServer(ourServer);
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourServer = new Server(0);
|
||||
|
||||
PatientProvider patientProvider = new PatientProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
ourServlet = new RestfulServer(ourCtx);
|
||||
|
||||
ourServlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
JettyUtil.startServer(ourServer);
|
||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
|
||||
public static class PatientProvider implements IResourceProvider {
|
||||
|
||||
@Create()
|
||||
public MethodOutcome create(@ResourceParam Patient theIdParam) {
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setDiagnostics(theIdParam.getNameFirstRep().getFamily());
|
||||
|
||||
|
||||
theIdParam.setId("1");
|
||||
theIdParam.getMeta().setVersionId("1");
|
||||
|
||||
|
||||
return new MethodOutcome(new IdType("Patient", "1"), true).setOperationOutcome(oo).setResource(theIdParam);
|
||||
}
|
||||
|
||||
|
@ -480,4 +450,33 @@ public class ServerMimetypeR4Test {
|
|||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() throws Exception {
|
||||
JettyUtil.closeServer(ourServer);
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
ourServer = new Server(0);
|
||||
|
||||
PatientProvider patientProvider = new PatientProvider();
|
||||
|
||||
ServletHandler proxyHandler = new ServletHandler();
|
||||
ourServlet = new RestfulServer(ourCtx);
|
||||
|
||||
ourServlet.setResourceProviders(patientProvider);
|
||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||
ourServer.setHandler(proxyHandler);
|
||||
JettyUtil.startServer(ourServer);
|
||||
ourPort = JettyUtil.getPortForStartedServer(ourServer);
|
||||
|
||||
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
builder.setConnectionManager(connectionManager);
|
||||
ourClient = builder.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -308,7 +308,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package ca.uhn.fhir.test.utilities.server;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR Test Utilities
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2019 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
public class ResourceProviderRule implements TestRule {
|
||||
|
||||
private final RestfulServerRule myRestfulServerRule;
|
||||
private Object myProvider;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceProviderRule(RestfulServerRule theRestfulServerRule, Object theProvider) {
|
||||
myRestfulServerRule = theRestfulServerRule;
|
||||
myProvider = theProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement base, Description description) {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
myRestfulServerRule.getRestfulServer().registerProvider(myProvider);
|
||||
try {
|
||||
base.evaluate();
|
||||
} finally {
|
||||
myRestfulServerRule.getRestfulServer().unregisterProvider(myProvider);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -112,4 +112,8 @@ public class RestfulServerRule implements TestRule {
|
|||
public RestfulServer getRestfulServer() {
|
||||
return myServlet;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return myPort;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -540,7 +540,7 @@ function updateURLParameter(url, param, paramVal){
|
|||
var temp = "";
|
||||
if (additionalURL) {
|
||||
tempArray = additionalURL.split("&");
|
||||
for (i=0; i<tempArray.length; i++){
|
||||
for (var i=0; i<tempArray.length; i++){
|
||||
if(tempArray[i].split('=')[0] !== param){
|
||||
newAdditionalURL += temp + tempArray[i];
|
||||
temp = "&";
|
||||
|
|
|
@ -275,7 +275,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -Dfile.encoding=UTF-8 -Xmx712m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
|
37
pom.xml
37
pom.xml
|
@ -582,9 +582,11 @@
|
|||
|
||||
<properties>
|
||||
|
||||
<fhir_core_version>4.1.0</fhir_core_version>
|
||||
<fhir_core_version>4.1.7-SNAPSHOT</fhir_core_version>
|
||||
<ucum_version>1.0.2</ucum_version>
|
||||
|
||||
<surefire_jvm_args>-Dfile.encoding=UTF-8 -Xmx1024m</surefire_jvm_args>
|
||||
|
||||
<!-- configure timestamp in MANIFEST.MF for maven-war-provider -->
|
||||
<maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss'Z'</maven.build.timestamp.format>
|
||||
|
||||
|
@ -615,7 +617,7 @@
|
|||
<jaxb_runtime_version>2.3.1</jaxb_runtime_version>
|
||||
<jersey_version>2.25.1</jersey_version>
|
||||
<!-- 9.4.17 seems to have issues -->
|
||||
<jetty_version>9.4.14.v20181114</jetty_version>
|
||||
<jetty_version>9.4.23.v20191118</jetty_version>
|
||||
<jsr305_version>3.0.2</jsr305_version>
|
||||
<!--<hibernate_version>5.2.10.Final</hibernate_version>-->
|
||||
<hibernate_version>5.4.6.Final</hibernate_version>
|
||||
|
@ -711,7 +713,7 @@
|
|||
<dependency>
|
||||
<groupId>com.icegreen</groupId>
|
||||
<artifactId>greenmail</artifactId>
|
||||
<version>1.5.10</version>
|
||||
<version>1.5.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.icegreen</groupId>
|
||||
|
@ -1657,9 +1659,9 @@
|
|||
<configuration>
|
||||
<redirectTestOutputToFile>true</redirectTestOutputToFile>
|
||||
<runOrder>random</runOrder>
|
||||
<argLine>-Dfile.encoding=UTF-8 -Xmx1024m</argLine>
|
||||
<argLine>@{argLine} ${surefire_jvm_args}</argLine>
|
||||
<forkCount>1.0C</forkCount>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
@ -2488,6 +2490,31 @@
|
|||
<modules>
|
||||
<module>hapi-fhir-jacoco</module>
|
||||
</modules>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<dumpOnExit>true</dumpOnExit>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-prepare-agent</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>CI</id>
|
||||
<properties>
|
||||
<surefire_jvm_args>-Dfile.encoding=UTF-8 -Xmx2048m -XX:TieredStopAtLevel=1 -XX:+UseParallelGC -Xverify:none -Dfile.encoding=UTF-8 -Xss128M -XX:MetaspaceSize=512M -XX:MaxMetaspaceSize=2048M</surefire_jvm_args>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>NOPARALLEL</id>
|
||||
|
|
|
@ -6,6 +6,42 @@
|
|||
<title>HAPI FHIR Changelog</title>
|
||||
</properties>
|
||||
<body>
|
||||
<release version="4.2.0" date="TBD">
|
||||
<action type="add">
|
||||
The version of a few dependencies have been bumped to the
|
||||
latest versions (dependent HAPI modules listed in brackets):
|
||||
<![CDATA[
|
||||
<ul>
|
||||
<li>Jetty (CLI): 9.4.14.v20181114 -> 9.4.23.v20191118</li>
|
||||
</ul>
|
||||
]]>
|
||||
</action>
|
||||
<action type="fix" issue="1583">
|
||||
As of FHIR R4, some fields that were previously of type reference are now of type canonical.
|
||||
One example is QuestionnaireResponse.questionnaire. Technically this means that this field
|
||||
should no longer contain a relative reference, but as they are sometimes used that way, HAPI
|
||||
FHIR will now try to be permissive and will index relative link canonical fields
|
||||
such as (Questionnaire/123) as though it actually was a local relative link. Thanks to
|
||||
Dean Atchley for reporting and providing a test case!
|
||||
</action>
|
||||
<action type="fix">
|
||||
ValueSet PreCalculation did not successfully expand valuesets when Lucene was not enabled
|
||||
in the JPA server. This has been corrected.
|
||||
</action>
|
||||
<action type="change">
|
||||
When parsing Bundle resources containing other resources, XML/JSON parsers have an option called
|
||||
"override resource ID with bundle entry fullUrl". This option previously caused any value
|
||||
found in Bundle.entry.fullUrl to override any value found in
|
||||
Bundle.entry.resource.id (meaning that the parsed resource would take its ID from
|
||||
the fullUrl even if that ID disagreed with the ID found in the resource itself. As of
|
||||
HAPI FHIR 4.1.0 the value in Bundle.entry.fullUrl will only be used to set the parsed resource
|
||||
ID if the resource has no ID present.
|
||||
</action>
|
||||
<action type="add">
|
||||
Chained searches using the _has search parameter as the chain value are now supported by
|
||||
the JPA server.
|
||||
</action>
|
||||
</release>
|
||||
<release version="4.1.0" date="2019-11-13" description="Jitterbug">
|
||||
<action type="add">
|
||||
The version of a few dependencies have been bumped to the
|
||||
|
|
|
@ -1,184 +1,186 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||
|
||||
<properties>
|
||||
<title>Hacking HAPI FHIR</title>
|
||||
</properties>
|
||||
|
||||
<body>
|
||||
|
||||
<section name="Hacking HAPI FHIR">
|
||||
|
||||
<p>
|
||||
This page contains useful information about how to get started in developing
|
||||
HAPI FHIR itself.
|
||||
</p>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Understanding the HAPI FHIR Codebase">
|
||||
|
||||
<p>
|
||||
The HAPI FHIR <a href="https://github.com/jamesagnew/hapi-fhir">Codebase</a>
|
||||
has a number of subprojects. You will typically need to interact with several
|
||||
of them in order to develop HAPI, but you generally don't need all of them.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following is a list of key subprojects you might open in your IDE:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-base"><b>hapi-fhir-base</b></a>:
|
||||
This is the core library, containing the parsers, client/server frameworks, and many other features. Note
|
||||
that this module does not contain any model classes (e.g. the Patient model class) as these are found
|
||||
in "structures" projects below.
|
||||
</li>
|
||||
<li>
|
||||
<b>hapi-fhir-structures-[version]</b>:
|
||||
There are several structures projects (e.g. <code>hapi-fhir-structures-dstu2</code>), each of
|
||||
which contains model classes for a specific version of FHIR.It is generally a good idea
|
||||
to open all of these in your IDE.
|
||||
</li>
|
||||
<li>
|
||||
<b>hapi-fhir-validation-resources-[version]</b>:
|
||||
There are several validation resources projects (e.g. <code>hapi-fhir-validation-resources-dstu2</code>), each of
|
||||
which contains text resources for the given version. These resources are text resources produced
|
||||
as a part of the FHIR specification build (e.g. StructureDefinitions, ValueSets, etc.)
|
||||
</li>
|
||||
<li>
|
||||
<b>hapi-fhir-jpaserver-base</b>:
|
||||
This module contains the JPA server.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Getting the Sources">
|
||||
<p style="float:right;">
|
||||
<a href="https://travis-ci.org/jamesagnew/hapi-fhir"><img src="https://travis-ci.org/jamesagnew/hapi-fhir.svg?branch=master" alt="Build Status"/></a>
|
||||
</p>
|
||||
<p>
|
||||
The best way to grab our sources is with Git. Grab the repository URL
|
||||
from our <a href="https://github.com/jamesagnew/hapi-fhir">GitHub page</a>.
|
||||
We try our best to ensure that the sources are always left in a buildable state. Check
|
||||
Travis (see the image/link on the right) to see if the sources currently build.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section name="Building HAPI FHIR">
|
||||
<p>
|
||||
HAPI is built primary using
|
||||
<a href="http://maven.apache.org/">Apache Maven</a>. Even if you are using an IDE,
|
||||
you should start by performing a command line build before trying to get
|
||||
everything working in an IDE.
|
||||
</p>
|
||||
<p>
|
||||
Execute the build with the following command:<br/>
|
||||
<code>mvn install</code>
|
||||
</p>
|
||||
<p>
|
||||
Note that this complete build takes a long time because of all of the unit tests
|
||||
being executed. At the end you should expect to see a screen resembling:<br/>
|
||||
<pre>[]INFO] ------------------------------------------------------------------------
|
||||
[INFO] Reactor Summary:
|
||||
[INFO]
|
||||
[INFO] HAPI-FHIR .......................................... SUCCESS [ 4.456 s]
|
||||
[INFO] HAPI FHIR - Deployable Artifact Parent POM ......... SUCCESS [ 2.841 s]
|
||||
[INFO] HAPI FHIR - Core Library ........................... SUCCESS [01:00 min]
|
||||
[INFO] HAPI Tinder Plugin ................................. SUCCESS [ 19.259 s]
|
||||
[INFO] HAPI FHIR Structures - DSTU1 (FHIR v0.80) .......... SUCCESS [01:40 min]
|
||||
[INFO] HAPI FHIR Structures - DSTU2 (FHIR v1.0.0) ......... SUCCESS [01:14 min]
|
||||
[INFO] HAPI FHIR Structures - DSTU3 ....................... SUCCESS [02:11 min]
|
||||
.... some lines removed .....
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] BUILD SUCCESS
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Total time: 20:45 min
|
||||
[INFO] Finished at: 2016-02-27T15:05:35+00:00</pre>
|
||||
</p>
|
||||
|
||||
<subsection name="Troubleshooting">
|
||||
|
||||
<p>
|
||||
If the build fails to execute successfully, try the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
The first thing to try is always a fresh clean build when things aren't working:<br/>
|
||||
<pre>mvn clean install</pre>
|
||||
</li>
|
||||
<li>
|
||||
<b>If you are trying to build a submodule</b> (e.g. <code>hapi-fhir-jpaserver-example</code>),
|
||||
try building the root project first. Especially when building from the Git <code>master</code>,
|
||||
often times there will be dependencies that require a fresh complete build (note that this is
|
||||
not generally an issue when building from a release version)<br/>
|
||||
<pre><![CDATA[cd [workspace]/hapi-fhir
|
||||
mvn install]]></pre>
|
||||
</li>
|
||||
<li>
|
||||
<b>If the build fails with memory issues (or mysteriously dies during unit tests)</b>,
|
||||
your build environment may be running out of memory. By default, the HAPI build executes
|
||||
unit tests in multiple parallel JVMs in order to save time. This can consume a lot of RAM
|
||||
and sometimes causes issues. Try executing with the following command to disable
|
||||
this behaviour:<br/>
|
||||
<pre>mvn -P ALLMODULES,NOPARALLEL install</pre>
|
||||
</li>
|
||||
<li>
|
||||
If you figure something else out, please <b>let us know</b> so that we can add it
|
||||
to this list!
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Importing into Eclipse">
|
||||
<p>
|
||||
This section shows how to import HAPI into Eclipse. There is no requirement
|
||||
to use Eclipse (IntelliJ/IDEA and Netbeans are both fine!) so feel free to
|
||||
skip this section.
|
||||
</p>
|
||||
<p>
|
||||
<b>Maven Import</b><br/>
|
||||
Import the HAPI projects as Maven Modules by selecing
|
||||
<code>File -> Import...</code> from the File menu. Then select
|
||||
<code>Existing Module Projects</code> as shown below.
|
||||
</p>
|
||||
<img src="./images/hacking_import.png"/><br/><br/>
|
||||
<p>
|
||||
<b>Select the Projects</b><br/>
|
||||
Next, browse to the directory where you checked out the HAPI FHIR sources.
|
||||
You might want to select only the projects you are interested in editing,
|
||||
in order to keep Eclipse's memory use down. You can always come back and
|
||||
import more later.
|
||||
</p>
|
||||
<img src="./images/hacking_import_step2.png"/>
|
||||
|
||||
<subsection name="Troubleshooting">
|
||||
|
||||
<p>
|
||||
When importing the HAPI projects into Eclipse, sometimes Eclipse
|
||||
will fail to correctly import libraries. If you import a module
|
||||
into Eclipse and it fails to compile with many errors relating to
|
||||
packages other than HAPI's, the following steps will fix this:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Delete the project from your Eclipse workspace</li>
|
||||
<li>
|
||||
On the local filesystem, delete the files <code>.project</code>
|
||||
and <code>.classpath</code>, and the directory <code>.settings</code>
|
||||
from each module you want to open.
|
||||
</li>
|
||||
<li>
|
||||
Import each module again using the instructions above
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
</body>
|
||||
|
||||
</document>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document xmlns="http://maven.apache.org/XDOC/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
|
||||
|
||||
<!-- This content has been migrated -->
|
||||
|
||||
<properties>
|
||||
<title>Hacking HAPI FHIR</title>
|
||||
</properties>
|
||||
|
||||
<body>
|
||||
|
||||
<section name="Hacking HAPI FHIR">
|
||||
|
||||
<p>
|
||||
This page contains useful information about how to get started in developing
|
||||
HAPI FHIR itself.
|
||||
</p>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Understanding the HAPI FHIR Codebase">
|
||||
|
||||
<p>
|
||||
The HAPI FHIR <a href="https://github.com/jamesagnew/hapi-fhir">Codebase</a>
|
||||
has a number of subprojects. You will typically need to interact with several
|
||||
of them in order to develop HAPI, but you generally don't need all of them.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following is a list of key subprojects you might open in your IDE:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://github.com/jamesagnew/hapi-fhir/tree/master/hapi-fhir-base"><b>hapi-fhir-base</b></a>:
|
||||
This is the core library, containing the parsers, client/server frameworks, and many other features. Note
|
||||
that this module does not contain any model classes (e.g. the Patient model class) as these are found
|
||||
in "structures" projects below.
|
||||
</li>
|
||||
<li>
|
||||
<b>hapi-fhir-structures-[version]</b>:
|
||||
There are several structures projects (e.g. <code>hapi-fhir-structures-dstu2</code>), each of
|
||||
which contains model classes for a specific version of FHIR.It is generally a good idea
|
||||
to open all of these in your IDE.
|
||||
</li>
|
||||
<li>
|
||||
<b>hapi-fhir-validation-resources-[version]</b>:
|
||||
There are several validation resources projects (e.g. <code>hapi-fhir-validation-resources-dstu2</code>), each of
|
||||
which contains text resources for the given version. These resources are text resources produced
|
||||
as a part of the FHIR specification build (e.g. StructureDefinitions, ValueSets, etc.)
|
||||
</li>
|
||||
<li>
|
||||
<b>hapi-fhir-jpaserver-base</b>:
|
||||
This module contains the JPA server.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Getting the Sources">
|
||||
<p style="float:right;">
|
||||
<a href="https://travis-ci.org/jamesagnew/hapi-fhir"><img src="https://travis-ci.org/jamesagnew/hapi-fhir.svg?branch=master" alt="Build Status"/></a>
|
||||
</p>
|
||||
<p>
|
||||
The best way to grab our sources is with Git. Grab the repository URL
|
||||
from our <a href="https://github.com/jamesagnew/hapi-fhir">GitHub page</a>.
|
||||
We try our best to ensure that the sources are always left in a buildable state. Check
|
||||
Travis (see the image/link on the right) to see if the sources currently build.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section name="Building HAPI FHIR">
|
||||
<p>
|
||||
HAPI is built primary using
|
||||
<a href="http://maven.apache.org/">Apache Maven</a>. Even if you are using an IDE,
|
||||
you should start by performing a command line build before trying to get
|
||||
everything working in an IDE.
|
||||
</p>
|
||||
<p>
|
||||
Execute the build with the following command:<br/>
|
||||
<code>mvn install</code>
|
||||
</p>
|
||||
<p>
|
||||
Note that this complete build takes a long time because of all of the unit tests
|
||||
being executed. At the end you should expect to see a screen resembling:<br/>
|
||||
<pre>[]INFO] ------------------------------------------------------------------------
|
||||
[INFO] Reactor Summary:
|
||||
[INFO]
|
||||
[INFO] HAPI-FHIR .......................................... SUCCESS [ 4.456 s]
|
||||
[INFO] HAPI FHIR - Deployable Artifact Parent POM ......... SUCCESS [ 2.841 s]
|
||||
[INFO] HAPI FHIR - Core Library ........................... SUCCESS [01:00 min]
|
||||
[INFO] HAPI Tinder Plugin ................................. SUCCESS [ 19.259 s]
|
||||
[INFO] HAPI FHIR Structures - DSTU1 (FHIR v0.80) .......... SUCCESS [01:40 min]
|
||||
[INFO] HAPI FHIR Structures - DSTU2 (FHIR v1.0.0) ......... SUCCESS [01:14 min]
|
||||
[INFO] HAPI FHIR Structures - DSTU3 ....................... SUCCESS [02:11 min]
|
||||
.... some lines removed .....
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] BUILD SUCCESS
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Total time: 20:45 min
|
||||
[INFO] Finished at: 2016-02-27T15:05:35+00:00</pre>
|
||||
</p>
|
||||
|
||||
<subsection name="Troubleshooting">
|
||||
|
||||
<p>
|
||||
If the build fails to execute successfully, try the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
The first thing to try is always a fresh clean build when things aren't working:<br/>
|
||||
<pre>mvn clean install</pre>
|
||||
</li>
|
||||
<li>
|
||||
<b>If you are trying to build a submodule</b> (e.g. <code>hapi-fhir-jpaserver-example</code>),
|
||||
try building the root project first. Especially when building from the Git <code>master</code>,
|
||||
often times there will be dependencies that require a fresh complete build (note that this is
|
||||
not generally an issue when building from a release version)<br/>
|
||||
<pre><![CDATA[cd [workspace]/hapi-fhir
|
||||
mvn install]]></pre>
|
||||
</li>
|
||||
<li>
|
||||
<b>If the build fails with memory issues (or mysteriously dies during unit tests)</b>,
|
||||
your build environment may be running out of memory. By default, the HAPI build executes
|
||||
unit tests in multiple parallel JVMs in order to save time. This can consume a lot of RAM
|
||||
and sometimes causes issues. Try executing with the following command to disable
|
||||
this behaviour:<br/>
|
||||
<pre>mvn -P ALLMODULES,NOPARALLEL install</pre>
|
||||
</li>
|
||||
<li>
|
||||
If you figure something else out, please <b>let us know</b> so that we can add it
|
||||
to this list!
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Importing into Eclipse">
|
||||
<p>
|
||||
This section shows how to import HAPI into Eclipse. There is no requirement
|
||||
to use Eclipse (IntelliJ/IDEA and Netbeans are both fine!) so feel free to
|
||||
skip this section.
|
||||
</p>
|
||||
<p>
|
||||
<b>Maven Import</b><br/>
|
||||
Import the HAPI projects as Maven Modules by selecing
|
||||
<code>File -> Import...</code> from the File menu. Then select
|
||||
<code>Existing Module Projects</code> as shown below.
|
||||
</p>
|
||||
<img src="./images/hacking_import.png"/><br/><br/>
|
||||
<p>
|
||||
<b>Select the Projects</b><br/>
|
||||
Next, browse to the directory where you checked out the HAPI FHIR sources.
|
||||
You might want to select only the projects you are interested in editing,
|
||||
in order to keep Eclipse's memory use down. You can always come back and
|
||||
import more later.
|
||||
</p>
|
||||
<img src="./images/hacking_import_step2.png"/>
|
||||
|
||||
<subsection name="Troubleshooting">
|
||||
|
||||
<p>
|
||||
When importing the HAPI projects into Eclipse, sometimes Eclipse
|
||||
will fail to correctly import libraries. If you import a module
|
||||
into Eclipse and it fails to compile with many errors relating to
|
||||
packages other than HAPI's, the following steps will fix this:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Delete the project from your Eclipse workspace</li>
|
||||
<li>
|
||||
On the local filesystem, delete the files <code>.project</code>
|
||||
and <code>.classpath</code>, and the directory <code>.settings</code>
|
||||
from each module you want to open.
|
||||
</li>
|
||||
<li>
|
||||
Import each module again using the instructions above
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</subsection>
|
||||
|
||||
</section>
|
||||
</body>
|
||||
|
||||
</document>
|
||||
|
|
Loading…
Reference in New Issue