Correct issues uncovered during connectathon
This commit is contained in:
parent
552842e547
commit
589059256f
|
@ -52,6 +52,7 @@ import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||||
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
import ca.uhn.fhir.rest.client.api.IRestfulClient;
|
||||||
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
|
import ca.uhn.fhir.util.VersionUtil;
|
||||||
import ca.uhn.fhir.validation.FhirValidator;
|
import ca.uhn.fhir.validation.FhirValidator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,6 +114,8 @@ public class FhirContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
private FhirContext(FhirVersionEnum theVersion, Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
private FhirContext(FhirVersionEnum theVersion, Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
||||||
|
VersionUtil.getVersion();
|
||||||
|
|
||||||
if (theVersion != null) {
|
if (theVersion != null) {
|
||||||
if (!theVersion.isPresentOnClasspath()) {
|
if (!theVersion.isPresentOnClasspath()) {
|
||||||
throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructuresForSpecifiedVersion", theVersion.name()));
|
throw new IllegalStateException(getLocalizer().getMessage(FhirContext.class, "noStructuresForSpecifiedVersion", theVersion.name()));
|
||||||
|
@ -465,9 +468,6 @@ public class FhirContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNarrativeGenerator(INarrativeGenerator theNarrativeGenerator) {
|
public void setNarrativeGenerator(INarrativeGenerator theNarrativeGenerator) {
|
||||||
if (theNarrativeGenerator != null) {
|
|
||||||
theNarrativeGenerator.setFhirContext(this);
|
|
||||||
}
|
|
||||||
myNarrativeGenerator = theNarrativeGenerator;
|
myNarrativeGenerator = theNarrativeGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,6 +509,8 @@ public class FhirContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2_1 DSTU 2.1}
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2_1 DSTU 2.1}
|
||||||
|
*
|
||||||
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
public static FhirContext forDstu2_1() {
|
public static FhirContext forDstu2_1() {
|
||||||
return new FhirContext(FhirVersionEnum.DSTU2_1);
|
return new FhirContext(FhirVersionEnum.DSTU2_1);
|
||||||
|
|
|
@ -30,8 +30,10 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IBase;
|
import org.hl7.fhir.instance.model.api.IBase;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.api.annotation.Description;
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
|
@ -108,6 +110,7 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
|
||||||
} else {
|
} else {
|
||||||
nextDef = theClassToElementDefinitions.get(next);
|
nextDef = theClassToElementDefinitions.get(next);
|
||||||
BaseRuntimeElementDefinition<?> nextDefForChoice = nextDef;
|
BaseRuntimeElementDefinition<?> nextDefForChoice = nextDef;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In HAPI 1.3 the following applied:
|
* In HAPI 1.3 the following applied:
|
||||||
* Elements which are called foo[x] and have a choice which is a profiled datatype must use the
|
* Elements which are called foo[x] and have a choice which is a profiled datatype must use the
|
||||||
|
@ -115,19 +118,19 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
|
||||||
* element fooString when encoded, because markdown is a profile of string. This is according to the
|
* element fooString when encoded, because markdown is a profile of string. This is according to the
|
||||||
* FHIR spec
|
* FHIR spec
|
||||||
*
|
*
|
||||||
* As of HAPI 1.4 this has been disabled after conversation with Grahame. It appears
|
* Note that as of HAPI 1.4 this applies only to non-primitive datatypes after discussion
|
||||||
* that it is not correct behaviour.
|
* with Grahame.
|
||||||
*/
|
*/
|
||||||
// if (nextDef instanceof IRuntimeDatatypeDefinition) {
|
if (nextDef instanceof IRuntimeDatatypeDefinition) {
|
||||||
// IRuntimeDatatypeDefinition nextDefDatatype = (IRuntimeDatatypeDefinition) nextDef;
|
IRuntimeDatatypeDefinition nextDefDatatype = (IRuntimeDatatypeDefinition) nextDef;
|
||||||
// if (nextDefDatatype.getProfileOf() != null) {
|
if (nextDefDatatype.getProfileOf() != null && !IPrimitiveType.class.isAssignableFrom(next)) {
|
||||||
// nextDefForChoice = null;
|
nextDefForChoice = null;
|
||||||
// nonPreferred = true;
|
nonPreferred = true;
|
||||||
// Class<? extends IBaseDatatype> profileType = nextDefDatatype.getProfileOf();
|
Class<? extends IBaseDatatype> profileType = nextDefDatatype.getProfileOf();
|
||||||
// BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(profileType);
|
BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(profileType);
|
||||||
// elementName = getElementName() + StringUtils.capitalize(elementDef.getName());
|
elementName = getElementName() + StringUtils.capitalize(elementDef.getName());
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
if (nextDefForChoice != null) {
|
if (nextDefForChoice != null) {
|
||||||
elementName = getElementName() + StringUtils.capitalize(nextDefForChoice.getName());
|
elementName = getElementName() + StringUtils.capitalize(nextDefForChoice.getName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ca.uhn.fhir.model.base.composite;
|
package ca.uhn.fhir.model.base.composite;
|
||||||
|
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
|
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
|
||||||
import ca.uhn.fhir.model.api.ICompositeDatatype;
|
import ca.uhn.fhir.model.api.ICompositeDatatype;
|
||||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||||
|
@ -28,10 +30,31 @@ import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||||
/**
|
/**
|
||||||
* @param <T> The narrative status enum type
|
* @param <T> The narrative status enum type
|
||||||
*/
|
*/
|
||||||
public abstract class BaseNarrativeDt<T extends Enum<?>> extends BaseIdentifiableElement implements ICompositeDatatype {
|
public abstract class BaseNarrativeDt<T extends Enum<?>> extends BaseIdentifiableElement implements ICompositeDatatype, INarrative {
|
||||||
|
|
||||||
public abstract BoundCodeDt<T> getStatus();
|
public abstract BoundCodeDt<T> getStatus();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDivAsString(String theString) {
|
||||||
|
getDiv().setValueAsString(theString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDivAsString() {
|
||||||
|
return getDiv().getValueAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public INarrative setStatusAsString(String theString) {
|
||||||
|
getStatus().setValueAsString(theString);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStatusAsString() {
|
||||||
|
return getStatus().getValueAsString();
|
||||||
|
}
|
||||||
|
|
||||||
public abstract XhtmlDt getDiv();
|
public abstract XhtmlDt getDiv();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,9 @@ import java.util.Properties;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.io.input.ReaderInputStream;
|
import org.apache.commons.io.input.ReaderInputStream;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.thymeleaf.Arguments;
|
import org.thymeleaf.Arguments;
|
||||||
import org.thymeleaf.Configuration;
|
import org.thymeleaf.Configuration;
|
||||||
import org.thymeleaf.TemplateEngine;
|
import org.thymeleaf.TemplateEngine;
|
||||||
|
@ -62,7 +64,7 @@ import org.thymeleaf.templateresolver.TemplateResolver;
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.IDatatype;
|
import ca.uhn.fhir.model.api.IDatatype;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
|
||||||
public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGenerator {
|
public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGenerator {
|
||||||
|
@ -77,10 +79,7 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
private boolean myIgnoreMissingTemplates = true;
|
private boolean myIgnoreMissingTemplates = true;
|
||||||
private volatile boolean myInitialized;
|
private volatile boolean myInitialized;
|
||||||
private HashMap<String, String> myNameToNarrativeTemplate;
|
private HashMap<String, String> myNameToNarrativeTemplate;
|
||||||
private HashMap<String, String> myNameToTitleTemplate;
|
|
||||||
private TemplateEngine myProfileTemplateEngine;
|
private TemplateEngine myProfileTemplateEngine;
|
||||||
private HashMap<String, String> myProfileToName;
|
|
||||||
private TemplateEngine myTitleTemplateEngine;
|
|
||||||
|
|
||||||
public BaseThymeleafNarrativeGenerator() {
|
public BaseThymeleafNarrativeGenerator() {
|
||||||
myThymeleafConfig = new Configuration();
|
myThymeleafConfig = new Configuration();
|
||||||
|
@ -90,44 +89,31 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
myThymeleafConfig.initialize();
|
myThymeleafConfig.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateNarrative(IBaseResource theResource, BaseNarrativeDt<?> theNarrative) {
|
|
||||||
generateNarrative(null, theResource, theNarrative);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFhirContext(FhirContext theFhirContext) {
|
public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) {
|
||||||
if (theFhirContext == null) {
|
|
||||||
throw new NullPointerException("Can not set theFhirContext to null");
|
|
||||||
}
|
|
||||||
if (myFhirContext != null && myFhirContext != theFhirContext) {
|
|
||||||
throw new IllegalStateException("Narrative generators may not be reused/shared across multiple FhirContext instances");
|
|
||||||
}
|
|
||||||
myFhirContext = theFhirContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt<?> theNarrative) {
|
|
||||||
if (!myInitialized) {
|
if (!myInitialized) {
|
||||||
initialize();
|
initialize(theContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = null;
|
String name = null;
|
||||||
if (StringUtils.isNotBlank(theProfile)) {
|
|
||||||
name = myProfileToName.get(theProfile);
|
|
||||||
}
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = myClassToName.get(theResource.getClass());
|
name = myClassToName.get(theResource.getClass());
|
||||||
}
|
}
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = myFhirContext.getResourceDefinition(theResource).getName().toLowerCase();
|
name = theContext.getResourceDefinition(theResource).getName().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
if (myIgnoreMissingTemplates) {
|
if (myIgnoreMissingTemplates) {
|
||||||
ourLog.debug("No narrative template available for profile: {}", theProfile);
|
ourLog.debug("No narrative template available for resorce: {}", name);
|
||||||
theNarrative.getDiv().setValueAsString("<div>No narrative template available for resource profile: " + theProfile + "</div>");
|
try {
|
||||||
theNarrative.getStatus().setValueAsString("empty");
|
theNarrative.setDivAsString("<div>No narrative template available for resource : " + name + "</div>");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// last resort..
|
||||||
|
}
|
||||||
|
theNarrative.setStatusAsString("empty");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
throw new DataFormatException("No narrative template for class " + theResource.getClass().getCanonicalName());
|
throw new DataFormatException("No narrative template for class " + theResource.getClass().getCanonicalName());
|
||||||
|
@ -137,7 +123,7 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
try {
|
try {
|
||||||
Context context = new Context();
|
Context context = new Context();
|
||||||
context.setVariable("resource", theResource);
|
context.setVariable("resource", theResource);
|
||||||
context.setVariable("fhirVersion", myFhirContext.getVersion().getVersion().name());
|
context.setVariable("fhirVersion", theContext.getVersion().getVersion().name());
|
||||||
|
|
||||||
String result = myProfileTemplateEngine.process(name, context);
|
String result = myProfileTemplateEngine.process(name, context);
|
||||||
|
|
||||||
|
@ -151,114 +137,27 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
theNarrative.getDiv().setValueAsString(result);
|
theNarrative.setDivAsString(result);
|
||||||
theNarrative.getStatus().setValueAsString("generated");
|
theNarrative.setStatusAsString("generated");
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (myIgnoreFailures) {
|
if (myIgnoreFailures) {
|
||||||
ourLog.error("Failed to generate narrative", e);
|
ourLog.error("Failed to generate narrative", e);
|
||||||
theNarrative.getDiv().setValueAsString("<div>No narrative available - Error: " + e.getMessage() + "</div>");
|
|
||||||
theNarrative.getStatus().setValueAsString("empty");
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
throw new DataFormatException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(IBaseResource theResource) {
|
|
||||||
return generateTitle( null, theResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(String theProfile, IBaseResource theResource) {
|
|
||||||
if (!myInitialized) {
|
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
ourLog.trace("Generating resource title {}", theResource);
|
|
||||||
|
|
||||||
String name = null;
|
|
||||||
if (StringUtils.isNotBlank(theProfile)) {
|
|
||||||
name = myProfileToName.get(theProfile);
|
|
||||||
}
|
|
||||||
if (name == null) {
|
|
||||||
name = myClassToName.get(theResource.getClass());
|
|
||||||
}
|
|
||||||
if (name == null) {
|
|
||||||
name = myFhirContext.getResourceDefinition(theResource).getName().toLowerCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
ourLog.trace("Template name is {}", name);
|
|
||||||
|
|
||||||
if (name == null) {
|
|
||||||
if (myIgnoreMissingTemplates) {
|
|
||||||
ourLog.debug("No title template available for profile: {}", theProfile);
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
throw new DataFormatException("No title template for class " + theResource.getClass().getCanonicalName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Context context = new Context();
|
theNarrative.setDivAsString("<div>No narrative available - Error: " + e.getMessage() + "</div>");
|
||||||
context.setVariable("resource", theResource);
|
} catch (Exception e1) {
|
||||||
context.setVariable("fhirVersion", myFhirContext.getVersion().getVersion().name());
|
// last resort..
|
||||||
|
|
||||||
String result = myTitleTemplateEngine.process(name, context);
|
|
||||||
|
|
||||||
ourLog.trace("Produced {}", result);
|
|
||||||
|
|
||||||
StringBuilder b = new StringBuilder();
|
|
||||||
boolean inTag = false;
|
|
||||||
for (int i = 0; i < result.length(); i++) {
|
|
||||||
char nextChar = result.charAt(i);
|
|
||||||
char prevChar = i > 0 ? result.charAt(i - 1) : '\n';
|
|
||||||
if (nextChar == '<') {
|
|
||||||
inTag = true;
|
|
||||||
continue;
|
|
||||||
} else if (inTag) {
|
|
||||||
if (nextChar == '>') {
|
|
||||||
inTag = false;
|
|
||||||
}
|
}
|
||||||
continue;
|
theNarrative.setStatusAsString("empty");
|
||||||
} else if (nextChar <= ' ') {
|
return;
|
||||||
if (prevChar <= ' ' || prevChar == '>') {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
b.append(' ');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b.append(nextChar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (b.length() > 0 && b.charAt(b.length() - 1) == ' ') {
|
|
||||||
b.setLength(b.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = b.toString();
|
|
||||||
if (result.startsWith("<") && result.contains(">")) {
|
|
||||||
result = result.substring(result.indexOf('>') + 1);
|
|
||||||
}
|
|
||||||
if (result.endsWith(">") && result.contains("<")) {
|
|
||||||
result = result.substring(0, result.lastIndexOf('<'));
|
|
||||||
}
|
|
||||||
|
|
||||||
result = result.replace(">", ">").replace("<", "<").replace("&", "&");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (myIgnoreFailures) {
|
|
||||||
ourLog.error("Failed to generate narrative", e);
|
|
||||||
return "No title available - Error: " + e.getMessage();
|
|
||||||
} else {
|
} else {
|
||||||
throw new DataFormatException(e);
|
throw new DataFormatException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected abstract List<String> getPropertyFile();
|
protected abstract List<String> getPropertyFile();
|
||||||
|
|
||||||
private Document getXhtmlDOMFor(final Reader source) {
|
private Document getXhtmlDOMFor(final Reader source) {
|
||||||
|
@ -270,17 +169,15 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void initialize() {
|
private synchronized void initialize(FhirContext theContext) {
|
||||||
if (myInitialized) {
|
if (myInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ourLog.info("Initializing narrative generator");
|
ourLog.info("Initializing narrative generator");
|
||||||
|
|
||||||
myProfileToName = new HashMap<String, String>();
|
|
||||||
myClassToName = new HashMap<Class<?>, String>();
|
myClassToName = new HashMap<Class<?>, String>();
|
||||||
myNameToNarrativeTemplate = new HashMap<String, String>();
|
myNameToNarrativeTemplate = new HashMap<String, String>();
|
||||||
myNameToTitleTemplate = new HashMap<String, String>();
|
|
||||||
|
|
||||||
List<String> propFileName = getPropertyFile();
|
List<String> propFileName = getPropertyFile();
|
||||||
|
|
||||||
|
@ -303,23 +200,11 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
myProfileTemplateEngine.setTemplateResolver(resolver);
|
myProfileTemplateEngine.setTemplateResolver(resolver);
|
||||||
StandardDialect dialect = new StandardDialect();
|
StandardDialect dialect = new StandardDialect();
|
||||||
HashSet<IProcessor> additionalProcessors = new HashSet<IProcessor>();
|
HashSet<IProcessor> additionalProcessors = new HashSet<IProcessor>();
|
||||||
additionalProcessors.add(new NarrativeAttributeProcessor());
|
additionalProcessors.add(new NarrativeAttributeProcessor(theContext));
|
||||||
dialect.setAdditionalProcessors(additionalProcessors);
|
dialect.setAdditionalProcessors(additionalProcessors);
|
||||||
myProfileTemplateEngine.setDialect(dialect);
|
myProfileTemplateEngine.setDialect(dialect);
|
||||||
myProfileTemplateEngine.initialize();
|
myProfileTemplateEngine.initialize();
|
||||||
}
|
}
|
||||||
{
|
|
||||||
myTitleTemplateEngine = new TemplateEngine();
|
|
||||||
TemplateResolver resolver = new TemplateResolver();
|
|
||||||
resolver.setResourceResolver(new TitleResourceResolver());
|
|
||||||
myTitleTemplateEngine.setTemplateResolver(resolver);
|
|
||||||
StandardDialect dialect = new StandardDialect();
|
|
||||||
HashSet<IProcessor> additionalProcessors = new HashSet<IProcessor>();
|
|
||||||
additionalProcessors.add(new NarrativeAttributeProcessor());
|
|
||||||
dialect.setAdditionalProcessors(additionalProcessors);
|
|
||||||
myTitleTemplateEngine.setDialect(dialect);
|
|
||||||
myTitleTemplateEngine.initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
myInitialized = true;
|
myInitialized = true;
|
||||||
}
|
}
|
||||||
|
@ -369,22 +254,14 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
|
|
||||||
String narrativePropName = name + ".narrative";
|
String narrativePropName = name + ".narrative";
|
||||||
String narrativeName = file.getProperty(narrativePropName);
|
String narrativeName = file.getProperty(narrativePropName);
|
||||||
String titlePropName = name + ".title";
|
if (isBlank(narrativeName)) {
|
||||||
String titleName = file.getProperty(titlePropName);
|
throw new ConfigurationException("Found property '" + nextKey + "' but no corresponding property '" + narrativePropName + "' in file " + propFileName);
|
||||||
if (isBlank(narrativeName) && isBlank(titleName)) {
|
|
||||||
throw new ConfigurationException("Found property '" + nextKey + "' but no corresponding property '" + narrativePropName + "' or '" + titlePropName + "' in file " + propFileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
myProfileToName.put(file.getProperty(nextKey), name);
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(narrativeName)) {
|
if (StringUtils.isNotBlank(narrativeName)) {
|
||||||
String narrative = IOUtils.toString(loadResource(narrativeName));
|
String narrative = IOUtils.toString(loadResource(narrativeName));
|
||||||
myNameToNarrativeTemplate.put(name, narrative);
|
myNameToNarrativeTemplate.put(name, narrative);
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotBlank(titleName)) {
|
|
||||||
String title = IOUtils.toString(loadResource(titleName));
|
|
||||||
myNameToTitleTemplate.put(name, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (nextKey.endsWith(".class")) {
|
} else if (nextKey.endsWith(".class")) {
|
||||||
|
|
||||||
|
@ -403,10 +280,6 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
clazz = null;
|
clazz = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (isBlank(narrativeName) && isBlank(titleName)) {
|
|
||||||
// throw new ConfigurationException("Found property '" + nextKey + "' but no corresponding property '" + narrativePropName + "' or '" + titlePropName + "' in file " + propFileName);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (clazz != null) {
|
if (clazz != null) {
|
||||||
myClassToName.put(clazz, name);
|
myClassToName.put(clazz, name);
|
||||||
}
|
}
|
||||||
|
@ -424,18 +297,7 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else if (nextKey.endsWith(".title")) {
|
} else if (nextKey.endsWith(".title")) {
|
||||||
String name = nextKey.substring(0, nextKey.indexOf(".title"));
|
ourLog.debug("Ignoring title property as narrative generator no longer generates titles: {}", nextKey);
|
||||||
if (isBlank(name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String titlePropName = name + ".title";
|
|
||||||
String titleName = file.getProperty(titlePropName);
|
|
||||||
if (StringUtils.isNotBlank(titleName)) {
|
|
||||||
String title = IOUtils.toString(loadResource(titleName));
|
|
||||||
myNameToTitleTemplate.put(name, title);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
throw new ConfigurationException("Invalid property name: " + nextKey);
|
throw new ConfigurationException("Invalid property name: " + nextKey);
|
||||||
}
|
}
|
||||||
|
@ -555,13 +417,13 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private FhirContext myFhirContext;
|
|
||||||
|
|
||||||
public class NarrativeAttributeProcessor extends AbstractAttrProcessor {
|
public class NarrativeAttributeProcessor extends AbstractAttrProcessor {
|
||||||
|
|
||||||
|
private FhirContext myContext;
|
||||||
|
|
||||||
protected NarrativeAttributeProcessor() {
|
protected NarrativeAttributeProcessor(FhirContext theContext) {
|
||||||
super("narrative");
|
super("narrative");
|
||||||
|
myContext = theContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -569,6 +431,7 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
protected ProcessorResult processAttribute(Arguments theArguments, Element theElement, String theAttributeName) {
|
protected ProcessorResult processAttribute(Arguments theArguments, Element theElement, String theAttributeName) {
|
||||||
final String attributeValue = theElement.getAttributeValue(theAttributeName);
|
final String attributeValue = theElement.getAttributeValue(theAttributeName);
|
||||||
|
@ -587,6 +450,7 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
}
|
}
|
||||||
|
|
||||||
Context context = new Context();
|
Context context = new Context();
|
||||||
|
context.setVariable("fhirVersion", myContext.getVersion().getVersion().name());
|
||||||
context.setVariable("resource", value);
|
context.setVariable("resource", value);
|
||||||
|
|
||||||
String name = null;
|
String name = null;
|
||||||
|
@ -599,10 +463,15 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
if (value instanceof IBaseResource) {
|
if (value instanceof IBaseResource) {
|
||||||
name = myFhirContext.getResourceDefinition((IBaseResource)value).getName();
|
name = myContext.getResourceDefinition((Class<? extends IBaseResource>) value).getName();
|
||||||
} else if (value instanceof IDatatype) {
|
} else if (value instanceof IDatatype) {
|
||||||
name = value.getClass().getSimpleName();
|
name = value.getClass().getSimpleName();
|
||||||
name = name.substring(0, name.length() - 2);
|
name = name.substring(0, name.length() - 2);
|
||||||
|
} else if (value instanceof IBaseDatatype) {
|
||||||
|
name = value.getClass().getSimpleName();
|
||||||
|
if (name.endsWith("Type")) {
|
||||||
|
name = name.substring(0, name.length() - 4);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new DataFormatException("Don't know how to determine name for type: " + value.getClass());
|
throw new DataFormatException("Don't know how to determine name for type: " + value.getClass());
|
||||||
}
|
}
|
||||||
|
@ -677,20 +546,4 @@ public abstract class BaseThymeleafNarrativeGenerator implements INarrativeGener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class TitleResourceResolver implements IResourceResolver {
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return getClass().getCanonicalName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getResourceAsStream(TemplateProcessingParameters theTemplateProcessingParameters, String theName) {
|
|
||||||
String template = myNameToTitleTemplate.get(theName);
|
|
||||||
if (template == null) {
|
|
||||||
ourLog.info("No narative template for resource profile: {}", theName);
|
|
||||||
return new ReaderInputStream(new StringReader(""));
|
|
||||||
}
|
|
||||||
return new ReaderInputStream(new StringReader(template));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.util.List;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
|
|
||||||
|
|
||||||
public class DefaultThymeleafNarrativeGenerator extends BaseThymeleafNarrativeGenerator implements INarrativeGenerator {
|
public class DefaultThymeleafNarrativeGenerator extends BaseThymeleafNarrativeGenerator implements INarrativeGenerator {
|
||||||
|
|
||||||
public static final String NARRATIVES_PROPERTIES = "classpath:ca/uhn/fhir/narrative/narratives.properties";
|
public static final String NARRATIVES_PROPERTIES = "classpath:ca/uhn/fhir/narrative/narratives.properties";
|
||||||
|
@ -35,7 +34,7 @@ public class DefaultThymeleafNarrativeGenerator extends BaseThymeleafNarrativeGe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<String> getPropertyFile() {
|
protected List<String> getPropertyFile() {
|
||||||
List<String> retVal=new ArrayList<String>();
|
List<String> retVal = new ArrayList<String>();
|
||||||
retVal.add(NARRATIVES_PROPERTIES);
|
retVal.add(NARRATIVES_PROPERTIES);
|
||||||
if (myUseHapiServerConformanceNarrative) {
|
if (myUseHapiServerConformanceNarrative) {
|
||||||
retVal.add(HAPISERVER_NARRATIVES_PROPERTIES);
|
retVal.add(HAPISERVER_NARRATIVES_PROPERTIES);
|
||||||
|
@ -44,25 +43,19 @@ public class DefaultThymeleafNarrativeGenerator extends BaseThymeleafNarrativeGe
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to <code>true</code> (default is <code>false</code>) a special custom narrative for the
|
* If set to <code>true</code> (default is <code>false</code>) a special custom narrative for the Conformance resource will be provided, which is designed to be used with HAPI {@link RestfulServer}
|
||||||
* Conformance resource will be provided, which is designed to be used with
|
* instances. This narrative provides a friendly search page which can assist users of the service.
|
||||||
* HAPI {@link RestfulServer} instances. This narrative provides a friendly search
|
|
||||||
* page which can assist users of the service.
|
|
||||||
*/
|
*/
|
||||||
public void setUseHapiServerConformanceNarrative(boolean theValue) {
|
public void setUseHapiServerConformanceNarrative(boolean theValue) {
|
||||||
myUseHapiServerConformanceNarrative=theValue;
|
myUseHapiServerConformanceNarrative = theValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to <code>true</code> (default is <code>false</code>) a special custom narrative for the
|
* If set to <code>true</code> (default is <code>false</code>) a special custom narrative for the Conformance resource will be provided, which is designed to be used with HAPI {@link RestfulServer}
|
||||||
* Conformance resource will be provided, which is designed to be used with
|
* instances. This narrative provides a friendly search page which can assist users of the service.
|
||||||
* HAPI {@link RestfulServer} instances. This narrative provides a friendly search
|
|
||||||
* page which can assist users of the service.
|
|
||||||
*/
|
*/
|
||||||
public boolean isUseHapiServerConformanceNarrative() {
|
public boolean isUseHapiServerConformanceNarrative() {
|
||||||
return myUseHapiServerConformanceNarrative;
|
return myUseHapiServerConformanceNarrative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,24 +21,12 @@ package ca.uhn.fhir.narrative;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseNarrativeDt;
|
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
|
||||||
|
|
||||||
public interface INarrativeGenerator {
|
public interface INarrativeGenerator {
|
||||||
|
|
||||||
void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt<?> theNarrative) throws DataFormatException;
|
void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative);
|
||||||
|
|
||||||
void generateNarrative(IBaseResource theResource, BaseNarrativeDt<?> theNarrative);
|
|
||||||
|
|
||||||
String generateTitle(IBaseResource theResource);
|
|
||||||
|
|
||||||
String generateTitle(String theProfile, IBaseResource theResource);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called automatically by the framework, you do not need to interact with this method.
|
|
||||||
*/
|
|
||||||
void setFhirContext(FhirContext theFhirContext);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,9 @@ import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype;
|
import org.hl7.fhir.instance.model.api.IBaseIntegerDatatype;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IDomainResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||||
|
@ -504,7 +506,7 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
case PRIMITIVE_XHTML_HL7ORG:
|
case PRIMITIVE_XHTML_HL7ORG:
|
||||||
case PRIMITIVE_XHTML: {
|
case PRIMITIVE_XHTML: {
|
||||||
if (!getSuppressNarratives()) {
|
if (!isSuppressNarratives()) {
|
||||||
IPrimitiveType<?> dt = (IPrimitiveType<?>) theNextValue;
|
IPrimitiveType<?> dt = (IPrimitiveType<?>) theNextValue;
|
||||||
if (theChildName != null) {
|
if (theChildName != null) {
|
||||||
theWriter.write(theChildName, dt.getValueAsString());
|
theWriter.write(theChildName, dt.getValueAsString());
|
||||||
|
@ -539,10 +541,17 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
||||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||||
if (gen != null && theResource instanceof IResource) {
|
if (gen != null) {
|
||||||
BaseNarrativeDt<?> narr = ((IResource) theResource).getText();
|
INarrative narr;
|
||||||
if (narr.getDiv().isEmpty()) {
|
if (theResource instanceof IResource) {
|
||||||
gen.generateNarrative(theResDef.getResourceProfile(), theResource, narr);
|
narr = ((IResource) theResource).getText();
|
||||||
|
} else if (theResource instanceof IDomainResource) {
|
||||||
|
narr = ((IDomainResource)theResource).getText();
|
||||||
|
} else {
|
||||||
|
narr = null;
|
||||||
|
}
|
||||||
|
if (narr != null && narr.isEmpty()) {
|
||||||
|
gen.generateNarrative(myContext, theResource, narr);
|
||||||
if (narr != null && !narr.isEmpty()) {
|
if (narr != null && !narr.isEmpty()) {
|
||||||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||||
|
|
|
@ -56,7 +56,9 @@ import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseXhtml;
|
import org.hl7.fhir.instance.model.api.IBaseXhtml;
|
||||||
|
import org.hl7.fhir.instance.model.api.IDomainResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||||
|
@ -576,22 +578,24 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
|
|
||||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||||
|
INarrative narr;
|
||||||
if (theResource instanceof IResource) {
|
if (theResource instanceof IResource) {
|
||||||
BaseNarrativeDt<?> narr = ((IResource) theResource).getText();
|
narr = ((IResource) theResource).getText();
|
||||||
if (gen != null && narr.isEmpty()) {
|
} else if (theResource instanceof IDomainResource) {
|
||||||
String resourceProfile = myContext.getResourceDefinition(theResource).getResourceProfile();
|
narr = ((IDomainResource)theResource).getText();
|
||||||
gen.generateNarrative(resourceProfile, theResource, narr);
|
} else {
|
||||||
|
narr = null;
|
||||||
}
|
}
|
||||||
if (narr.isEmpty() == false) {
|
if (gen != null && narr.isEmpty()) {
|
||||||
|
gen.generateNarrative(myContext, theResource, narr);
|
||||||
|
}
|
||||||
|
if (narr != null && narr.isEmpty() == false) {
|
||||||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||||
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
||||||
encodeChildElementToStreamWriter(theResource, theEventWriter, narr, childName, type, null, theContainedResource, nextChildElem);
|
encodeChildElementToStreamWriter(theResource, theEventWriter, narr, childName, type, null, theContainedResource, nextChildElem);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Narrative generation not currently supported for HL7org structures
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextChild instanceof RuntimeChildContainedResources) {
|
if (nextChild instanceof RuntimeChildContainedResources) {
|
||||||
|
|
|
@ -27,14 +27,14 @@ import ca.uhn.fhir.parser.IParser;
|
||||||
|
|
||||||
public enum EncodingEnum {
|
public enum EncodingEnum {
|
||||||
|
|
||||||
XML(Constants.CT_FHIR_XML, Constants.CT_ATOM_XML, "application/xml", Constants.FORMAT_XML) {
|
XML(Constants.CT_FHIR_XML, Constants.CT_ATOM_XML, Constants.FORMAT_XML) {
|
||||||
@Override
|
@Override
|
||||||
public IParser newParser(FhirContext theContext) {
|
public IParser newParser(FhirContext theContext) {
|
||||||
return theContext.newXmlParser();
|
return theContext.newXmlParser();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
JSON(Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON, Constants.CT_JSON, Constants.FORMAT_JSON) {
|
JSON(Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON, Constants.FORMAT_JSON) {
|
||||||
@Override
|
@Override
|
||||||
public IParser newParser(FhirContext theContext) {
|
public IParser newParser(FhirContext theContext) {
|
||||||
return theContext.newJsonParser();
|
return theContext.newJsonParser();
|
||||||
|
@ -50,7 +50,6 @@ public enum EncodingEnum {
|
||||||
for (EncodingEnum next : values()) {
|
for (EncodingEnum next : values()) {
|
||||||
ourContentTypeToEncoding.put(next.getBundleContentType(), next);
|
ourContentTypeToEncoding.put(next.getBundleContentType(), next);
|
||||||
ourContentTypeToEncoding.put(next.getResourceContentType(), next);
|
ourContentTypeToEncoding.put(next.getResourceContentType(), next);
|
||||||
ourContentTypeToEncoding.put(next.getBrowserFriendlyBundleContentType(), next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -67,13 +66,11 @@ public enum EncodingEnum {
|
||||||
|
|
||||||
private String myResourceContentType;
|
private String myResourceContentType;
|
||||||
private String myBundleContentType;
|
private String myBundleContentType;
|
||||||
private String myBrowserFriendlyContentType;
|
|
||||||
private String myFormatContentType;
|
private String myFormatContentType;
|
||||||
|
|
||||||
EncodingEnum(String theResourceContentType, String theBundleContentType, String theBrowserFriendlyContentType, String theFormatContentType) {
|
EncodingEnum(String theResourceContentType, String theBundleContentType, String theFormatContentType) {
|
||||||
myResourceContentType = theResourceContentType;
|
myResourceContentType = theResourceContentType;
|
||||||
myBundleContentType = theBundleContentType;
|
myBundleContentType = theBundleContentType;
|
||||||
myBrowserFriendlyContentType = theBrowserFriendlyContentType;
|
|
||||||
myFormatContentType = theFormatContentType;
|
myFormatContentType = theFormatContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +88,6 @@ public enum EncodingEnum {
|
||||||
return myResourceContentType;
|
return myResourceContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBrowserFriendlyBundleContentType() {
|
|
||||||
return myBrowserFriendlyContentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EncodingEnum forContentType(String theContentType) {
|
public static EncodingEnum forContentType(String theContentType) {
|
||||||
return ourContentTypeToEncoding.get(theContentType);
|
return ourContentTypeToEncoding.get(theContentType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,15 +43,14 @@ public abstract class RestfulResponse<T extends RequestDetails> implements IRest
|
||||||
public final Object streamResponseAsResource(IBaseResource resource, boolean prettyPrint, Set<SummaryEnum> summaryMode,
|
public final Object streamResponseAsResource(IBaseResource resource, boolean prettyPrint, Set<SummaryEnum> summaryMode,
|
||||||
int statusCode, boolean respondGzip, boolean addContentLocationHeader)
|
int statusCode, boolean respondGzip, boolean addContentLocationHeader)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), resource, prettyPrint, summaryMode, statusCode, respondGzip, addContentLocationHeader,
|
return RestfulServerUtils.streamResponseAsResource(theRequestDetails.getServer(), resource, summaryMode, statusCode, addContentLocationHeader, respondGzip, getRequestDetails());
|
||||||
respondGzip, getRequestDetails());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object streamResponseAsBundle(Bundle bundle, Set<SummaryEnum> summaryMode, boolean respondGzip, boolean requestIsBrowser)
|
public Object streamResponseAsBundle(Bundle bundle, Set<SummaryEnum> summaryMode, boolean respondGzip, boolean requestIsBrowser)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return RestfulServerUtils.streamResponseAsBundle(theRequestDetails.getServer(), bundle, summaryMode, requestIsBrowser, respondGzip, getRequestDetails());
|
return RestfulServerUtils.streamResponseAsBundle(theRequestDetails.getServer(), bundle, summaryMode, respondGzip, getRequestDetails());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -72,6 +72,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
import ca.uhn.fhir.rest.server.exceptions.NotModifiedException;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
import ca.uhn.fhir.util.UrlUtil;
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
|
@ -112,9 +113,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
private boolean myUseBrowserFriendlyContentTypes;
|
private boolean myUseBrowserFriendlyContentTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Note that if no {@link FhirContext} is passed in to the server (either through the constructor, or
|
* Constructor. Note that if no {@link FhirContext} is passed in to the server (either through the constructor, or through {@link #setFhirContext(FhirContext)}) the server will determine which
|
||||||
* through {@link #setFhirContext(FhirContext)}) the server will determine which version of FHIR to support through
|
* version of FHIR to support through classpath scanning. This is brittle, and it is highly recommended to explicitly specify a FHIR version.
|
||||||
* classpath scanning. This is brittle, and it is highly recommended to explicitly specify a FHIR version.
|
|
||||||
*/
|
*/
|
||||||
public RestfulServer() {
|
public RestfulServer() {
|
||||||
this(null);
|
this(null);
|
||||||
|
@ -137,8 +137,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
/**
|
/**
|
||||||
* This method is called prior to sending a response to incoming requests. It is used to add custom headers.
|
* This method is called prior to sending a response to incoming requests. It is used to add custom headers.
|
||||||
* <p>
|
* <p>
|
||||||
* Use caution if overriding this method: it is recommended to call <code>super.addHeadersToResponse</code> to avoid
|
* Use caution if overriding this method: it is recommended to call <code>super.addHeadersToResponse</code> to avoid inadvertantly disabling functionality.
|
||||||
* inadvertantly disabling functionality.
|
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void addHeadersToResponse(HttpServletResponse theHttpResponse) {
|
public void addHeadersToResponse(HttpServletResponse theHttpResponse) {
|
||||||
|
@ -375,9 +374,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default encoding to return (XML/JSON) if an incoming request does not specify a preference (either
|
* Returns the default encoding to return (XML/JSON) if an incoming request does not specify a preference (either with the <code>_format</code> URL parameter, or with an <code>Accept</code> header
|
||||||
* with the <code>_format</code> URL parameter, or with an <code>Accept</code> header in the request. The default is
|
* in the request. The default is {@link EncodingEnum#XML}. Will not return null.
|
||||||
* {@link EncodingEnum#XML}. Will not return null.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public EncodingEnum getDefaultResponseEncoding() {
|
public EncodingEnum getDefaultResponseEncoding() {
|
||||||
|
@ -390,8 +388,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link FhirContext} associated with this server. For efficient processing, resource providers and plain
|
* Gets the {@link FhirContext} associated with this server. For efficient processing, resource providers and plain providers should generally use this context if one is needed, as opposed to
|
||||||
* providers should generally use this context if one is needed, as opposed to creating their own.
|
* creating their own.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public FhirContext getFhirContext() {
|
public FhirContext getFhirContext() {
|
||||||
|
@ -428,8 +426,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows users of RestfulServer to override the getRequestPath method to let them build their custom request path
|
* Allows users of RestfulServer to override the getRequestPath method to let them build their custom request path implementation
|
||||||
* implementation
|
|
||||||
*
|
*
|
||||||
* @param requestFullPath
|
* @param requestFullPath
|
||||||
* the full request path
|
* the full request path
|
||||||
|
@ -455,8 +452,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the server address strategy, which is used to determine what base URL to provide clients to refer to this
|
* Get the server address strategy, which is used to determine what base URL to provide clients to refer to this server. Defaults to an instance of {@link IncomingRequestAddressStrategy}
|
||||||
* server. Defaults to an instance of {@link IncomingRequestAddressStrategy}
|
|
||||||
*/
|
*/
|
||||||
public IServerAddressStrategy getServerAddressStrategy() {
|
public IServerAddressStrategy getServerAddressStrategy() {
|
||||||
return myServerAddressStrategy;
|
return myServerAddressStrategy;
|
||||||
|
@ -476,19 +472,17 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the method bindings for this server which are not specific to any particular resource type. This method is
|
* Returns the method bindings for this server which are not specific to any particular resource type. This method is internal to HAPI and developers generally do not need to interact with it. Use
|
||||||
* internal to HAPI and developers generally do not need to interact with it. Use with caution, as it may change.
|
* with caution, as it may change.
|
||||||
*/
|
*/
|
||||||
public List<BaseMethodBinding<?>> getServerBindings() {
|
public List<BaseMethodBinding<?>> getServerBindings() {
|
||||||
return myServerBinding.getMethodBindings();
|
return myServerBinding.getMethodBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the server conformance provider, which is the provider that is used to generate the server's conformance
|
* Returns the server conformance provider, which is the provider that is used to generate the server's conformance (metadata) statement if one has been explicitly defined.
|
||||||
* (metadata) statement if one has been explicitly defined.
|
|
||||||
* <p>
|
* <p>
|
||||||
* By default, the ServerConformanceProvider for the declared version of FHIR is used, but this can be changed, or
|
* By default, the ServerConformanceProvider for the declared version of FHIR is used, but this can be changed, or set to <code>null</code> to use the appropriate one for the given FHIR version.
|
||||||
* set to <code>null</code> to use the appropriate one for the given FHIR version.
|
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public Object getServerConformanceProvider() {
|
public Object getServerConformanceProvider() {
|
||||||
|
@ -496,8 +490,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the server's name, as exported in conformance profiles exported by the server. This is informational only,
|
* Gets the server's name, as exported in conformance profiles exported by the server. This is informational only, but can be helpful to set with something appropriate.
|
||||||
* but can be helpful to set with something appropriate.
|
|
||||||
*
|
*
|
||||||
* @see RestfulServer#setServerName(String)
|
* @see RestfulServer#setServerName(String)
|
||||||
*/
|
*/
|
||||||
|
@ -510,8 +503,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the server's version, as exported in conformance profiles exported by the server. This is informational only,
|
* Gets the server's version, as exported in conformance profiles exported by the server. This is informational only, but can be helpful to set with something appropriate.
|
||||||
* but can be helpful to set with something appropriate.
|
|
||||||
*/
|
*/
|
||||||
public String getServerVersion() {
|
public String getServerVersion() {
|
||||||
return myServerVersion;
|
return myServerVersion;
|
||||||
|
@ -621,12 +613,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actualy invoke the server method. This call is to a HAPI method binding, which is an object that wraps a
|
* Actualy invoke the server method. This call is to a HAPI method binding, which is an object that wraps a specific implementing (user-supplied) method, but handles its input and provides
|
||||||
* specific implementing (user-supplied) method, but handles its input and provides its output back to the
|
* its output back to the client.
|
||||||
* client.
|
|
||||||
*
|
*
|
||||||
* This is basically the end of processing for a successful request, since the method binding replies to the
|
* This is basically the end of processing for a successful request, since the method binding replies to the client and closes the response.
|
||||||
* client and closes the response.
|
|
||||||
*/
|
*/
|
||||||
resourceMethod.invokeServer(this, requestDetails);
|
resourceMethod.invokeServer(this, requestDetails);
|
||||||
|
|
||||||
|
@ -660,12 +650,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have caught an exception during request processing. This might be because a handling method threw
|
* We have caught an exception during request processing. This might be because a handling method threw something they wanted to throw (e.g. UnprocessableEntityException because the request
|
||||||
* something they wanted to throw (e.g. UnprocessableEntityException because the request had business
|
* had business requirement problems) or it could be due to bugs (e.g. NullPointerException).
|
||||||
* requirement problems) or it could be due to bugs (e.g. NullPointerException).
|
|
||||||
*
|
*
|
||||||
* First we let the interceptors have a crack at converting the exception into something HAPI can use
|
* First we let the interceptors have a crack at converting the exception into something HAPI can use (BaseServerResponseException)
|
||||||
* (BaseServerResponseException)
|
|
||||||
*/
|
*/
|
||||||
BaseServerResponseException exception = null;
|
BaseServerResponseException exception = null;
|
||||||
for (int i = getInterceptors().size() - 1; i >= 0; i--) {
|
for (int i = getInterceptors().size() - 1; i >= 0; i--) {
|
||||||
|
@ -678,8 +666,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If none of the interceptors converted the exception, default behaviour is to keep the exception as-is if it
|
* If none of the interceptors converted the exception, default behaviour is to keep the exception as-is if it extends BaseServerResponseException, otherwise wrap it in an
|
||||||
* extends BaseServerResponseException, otherwise wrap it in an InternalErrorException.
|
* InternalErrorException.
|
||||||
*/
|
*/
|
||||||
if (exception == null) {
|
if (exception == null) {
|
||||||
exception = DEFAULT_EXCEPTION_HANDLER.preProcessOutgoingException(requestDetails, e, theRequest);
|
exception = DEFAULT_EXCEPTION_HANDLER.preProcessOutgoingException(requestDetails, e, theRequest);
|
||||||
|
@ -711,9 +699,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the server. Note that this method is final to avoid accidentally introducing bugs in implementations,
|
* Initializes the server. Note that this method is final to avoid accidentally introducing bugs in implementations, but subclasses may put initialization code in {@link #initialize()}, which is
|
||||||
* but subclasses may put initialization code in {@link #initialize()}, which is called immediately before beginning
|
* called immediately before beginning initialization of the restful server's internal init.
|
||||||
* initialization of the restful server's internal init.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final void init() throws ServletException {
|
public final void init() throws ServletException {
|
||||||
|
@ -782,13 +769,11 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method may be overridden by subclasses to do perform initialization that needs to be performed prior to the
|
* This method may be overridden by subclasses to do perform initialization that needs to be performed prior to the server being used.
|
||||||
* server being used.
|
|
||||||
*
|
*
|
||||||
* @throws ServletException
|
* @throws ServletException
|
||||||
* If the initialization failed. Note that you should consider throwing {@link UnavailableException}
|
* If the initialization failed. Note that you should consider throwing {@link UnavailableException} (which extends {@link ServletException}), as this is a flag to the servlet container
|
||||||
* (which extends {@link ServletException}), as this is a flag to the servlet container that the servlet
|
* that the servlet is not usable.
|
||||||
* is not usable.
|
|
||||||
*/
|
*/
|
||||||
protected void initialize() throws ServletException {
|
protected void initialize() throws ServletException {
|
||||||
// nothing by default
|
// nothing by default
|
||||||
|
@ -845,8 +830,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the server "pretty print" responses by default (requesting clients can always override this default by
|
* Should the server "pretty print" responses by default (requesting clients can always override this default by supplying an <code>Accept</code> header in the request, or a <code>_pretty</code>
|
||||||
* supplying an <code>Accept</code> header in the request, or a <code>_pretty</code> parameter in the request URL.
|
* parameter in the request URL.
|
||||||
* <p>
|
* <p>
|
||||||
* The default is <code>false</code>
|
* The default is <code>false</code>
|
||||||
* </p>
|
* </p>
|
||||||
|
@ -859,14 +844,18 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the server attempt to decompress incoming request contents (default is <code>true</code>). Typically this
|
* Should the server attempt to decompress incoming request contents (default is <code>true</code>). Typically this should be set to <code>true</code> unless the server has other configuration to
|
||||||
* should be set to <code>true</code> unless the server has other configuration to deal with decompressing request
|
* deal with decompressing request bodies (e.g. a filter applied to the whole server).
|
||||||
* bodies (e.g. a filter applied to the whole server).
|
|
||||||
*/
|
*/
|
||||||
public boolean isUncompressIncomingContents() {
|
public boolean isUncompressIncomingContents() {
|
||||||
return myUncompressIncomingContents;
|
return myUncompressIncomingContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated This feature did not work well, and will be removed. Use {@link ResponseHighlighterInterceptor} instead as an interceptor on your server and it will provide more useful syntax
|
||||||
|
* highlighting. Deprocated in 1.4
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public boolean isUseBrowserFriendlyContentTypes() {
|
public boolean isUseBrowserFriendlyContentTypes() {
|
||||||
return myUseBrowserFriendlyContentTypes;
|
return myUseBrowserFriendlyContentTypes;
|
||||||
|
@ -946,8 +935,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a single provider. This could be a Resource Provider or a "plain" provider not associated with any
|
* Register a single provider. This could be a Resource Provider or a "plain" provider not associated with any resource.
|
||||||
* resource.
|
|
||||||
*
|
*
|
||||||
* @param provider
|
* @param provider
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
|
@ -1005,7 +993,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
String resourceName = getFhirContext().getResourceDefinition(resourceType).getName();
|
String resourceName = getFhirContext().getResourceDefinition(resourceType).getName();
|
||||||
if (myTypeToProvider.containsKey(resourceName)) {
|
if (myTypeToProvider.containsKey(resourceName)) {
|
||||||
throw new ServletException("Multiple resource providers return resource type[" + resourceName + "]: First[" + myTypeToProvider.get(resourceName).getClass().getCanonicalName() + "] and Second[" + rsrcProvider.getClass().getCanonicalName() + "]");
|
throw new ServletException("Multiple resource providers return resource type[" + resourceName + "]: First[" + myTypeToProvider.get(resourceName).getClass().getCanonicalName()
|
||||||
|
+ "] and Second[" + rsrcProvider.getClass().getCanonicalName() + "]");
|
||||||
}
|
}
|
||||||
if (!inInit) {
|
if (!inInit) {
|
||||||
myResourceProviders.add(rsrcProvider);
|
myResourceProviders.add(rsrcProvider);
|
||||||
|
@ -1118,9 +1107,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the profile tagging behaviour for the server. When set to a value other than {@link AddProfileTagEnum#NEVER}
|
* Sets the profile tagging behaviour for the server. When set to a value other than {@link AddProfileTagEnum#NEVER} (which is the default), the server will automatically add a profile tag based on
|
||||||
* (which is the default), the server will automatically add a profile tag based on the class of the resource(s)
|
* the class of the resource(s) being returned.
|
||||||
* being returned.
|
|
||||||
*
|
*
|
||||||
* @param theAddProfileTag
|
* @param theAddProfileTag
|
||||||
* The behaviour enum (must not be null)
|
* The behaviour enum (must not be null)
|
||||||
|
@ -1141,8 +1129,8 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the server "pretty print" responses by default (requesting clients can always override this default by
|
* Should the server "pretty print" responses by default (requesting clients can always override this default by supplying an <code>Accept</code> header in the request, or a <code>_pretty</code>
|
||||||
* supplying an <code>Accept</code> header in the request, or a <code>_pretty</code> parameter in the request URL.
|
* parameter in the request URL.
|
||||||
* <p>
|
* <p>
|
||||||
* The default is <code>false</code>
|
* The default is <code>false</code>
|
||||||
* </p>
|
* </p>
|
||||||
|
@ -1155,12 +1143,10 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the default encoding to return (XML/JSON) if an incoming request does not specify a preference (either with
|
* Sets the default encoding to return (XML/JSON) if an incoming request does not specify a preference (either with the <code>_format</code> URL parameter, or with an <code>Accept</code> header in
|
||||||
* the <code>_format</code> URL parameter, or with an <code>Accept</code> header in the request. The default is
|
* the request. The default is {@link EncodingEnum#XML}.
|
||||||
* {@link EncodingEnum#XML}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Note when testing this feature: Some browsers will include "application/xml" in their Accept header, which means
|
* Note when testing this feature: Some browsers will include "application/xml" in their Accept header, which means that the
|
||||||
* that the
|
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void setDefaultResponseEncoding(EncodingEnum theDefaultResponseEncoding) {
|
public void setDefaultResponseEncoding(EncodingEnum theDefaultResponseEncoding) {
|
||||||
|
@ -1169,8 +1155,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets (enables/disables) the server support for ETags. Must not be <code>null</code>. Default is
|
* Sets (enables/disables) the server support for ETags. Must not be <code>null</code>. Default is {@link #DEFAULT_ETAG_SUPPORT}
|
||||||
* {@link #DEFAULT_ETAG_SUPPORT}
|
|
||||||
*
|
*
|
||||||
* @param theETagSupport
|
* @param theETagSupport
|
||||||
* The ETag support mode
|
* The ETag support mode
|
||||||
|
@ -1278,8 +1263,7 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a server address strategy, which is used to determine what base URL to provide clients to refer to this
|
* Provide a server address strategy, which is used to determine what base URL to provide clients to refer to this server. Defaults to an instance of {@link IncomingRequestAddressStrategy}
|
||||||
* server. Defaults to an instance of {@link IncomingRequestAddressStrategy}
|
|
||||||
*/
|
*/
|
||||||
public void setServerAddressStrategy(IServerAddressStrategy theServerAddressStrategy) {
|
public void setServerAddressStrategy(IServerAddressStrategy theServerAddressStrategy) {
|
||||||
Validate.notNull(theServerAddressStrategy, "Server address strategy can not be null");
|
Validate.notNull(theServerAddressStrategy, "Server address strategy can not be null");
|
||||||
|
@ -1287,17 +1271,15 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the server conformance provider, which is the provider that is used to generate the server's conformance
|
* Returns the server conformance provider, which is the provider that is used to generate the server's conformance (metadata) statement.
|
||||||
* (metadata) statement.
|
|
||||||
* <p>
|
* <p>
|
||||||
* By default, the ServerConformanceProvider implementation for the declared version of FHIR is used, but this can be
|
* By default, the ServerConformanceProvider implementation for the declared version of FHIR is used, but this can be changed, or set to <code>null</code> if you do not wish to export a conformance
|
||||||
* changed, or set to <code>null</code> if you do not wish to export a conformance statement.
|
* statement.
|
||||||
* </p>
|
* </p>
|
||||||
* Note that this method can only be called before the server is initialized.
|
* Note that this method can only be called before the server is initialized.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException
|
* @throws IllegalStateException
|
||||||
* Note that this method can only be called prior to {@link #init() initialization} and will throw an
|
* Note that this method can only be called prior to {@link #init() initialization} and will throw an {@link IllegalStateException} if called after that.
|
||||||
* {@link IllegalStateException} if called after that.
|
|
||||||
*/
|
*/
|
||||||
public void setServerConformanceProvider(Object theServerConformanceProvider) {
|
public void setServerConformanceProvider(Object theServerConformanceProvider) {
|
||||||
if (myStarted) {
|
if (myStarted) {
|
||||||
|
@ -1320,34 +1302,32 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the server's name, as exported in conformance profiles exported by the server. This is informational only,
|
* Sets the server's name, as exported in conformance profiles exported by the server. This is informational only, but can be helpful to set with something appropriate.
|
||||||
* but can be helpful to set with something appropriate.
|
|
||||||
*/
|
*/
|
||||||
public void setServerName(String theServerName) {
|
public void setServerName(String theServerName) {
|
||||||
myServerName = theServerName;
|
myServerName = theServerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the server's version, as exported in conformance profiles exported by the server. This is informational only,
|
* Gets the server's version, as exported in conformance profiles exported by the server. This is informational only, but can be helpful to set with something appropriate.
|
||||||
* but can be helpful to set with something appropriate.
|
|
||||||
*/
|
*/
|
||||||
public void setServerVersion(String theServerVersion) {
|
public void setServerVersion(String theServerVersion) {
|
||||||
myServerVersion = theServerVersion;
|
myServerVersion = theServerVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should the server attempt to decompress incoming request contents (default is <code>true</code>). Typically this
|
* Should the server attempt to decompress incoming request contents (default is <code>true</code>). Typically this should be set to <code>true</code> unless the server has other configuration to
|
||||||
* should be set to <code>true</code> unless the server has other configuration to deal with decompressing request
|
* deal with decompressing request bodies (e.g. a filter applied to the whole server).
|
||||||
* bodies (e.g. a filter applied to the whole server).
|
|
||||||
*/
|
*/
|
||||||
public void setUncompressIncomingContents(boolean theUncompressIncomingContents) {
|
public void setUncompressIncomingContents(boolean theUncompressIncomingContents) {
|
||||||
myUncompressIncomingContents = theUncompressIncomingContents;
|
myUncompressIncomingContents = theUncompressIncomingContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to <code>true</code> (default is false), the server will use browser friendly content-types (instead of
|
* @deprecated This feature did not work well, and will be removed. Use {@link ResponseHighlighterInterceptor} instead as an interceptor on your server and it will provide more useful syntax
|
||||||
* standard FHIR ones) when it detects that the request is coming from a browser instead of a FHIR
|
* highlighting. Deprocated in 1.4
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setUseBrowserFriendlyContentTypes(boolean theUseBrowserFriendlyContentTypes) {
|
public void setUseBrowserFriendlyContentTypes(boolean theUseBrowserFriendlyContentTypes) {
|
||||||
myUseBrowserFriendlyContentTypes = theUseBrowserFriendlyContentTypes;
|
myUseBrowserFriendlyContentTypes = theUseBrowserFriendlyContentTypes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -545,8 +545,7 @@ public class RestfulServerUtils {
|
||||||
return prettyPrint;
|
return prettyPrint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object streamResponseAsBundle(IRestfulServerDefaults theServer, Bundle bundle, Set<SummaryEnum> theSummaryMode,
|
public static Object streamResponseAsBundle(IRestfulServerDefaults theServer, Bundle bundle, Set<SummaryEnum> theSummaryMode, boolean respondGzip, RequestDetails theRequestDetails)
|
||||||
boolean theRequestIsBrowser, boolean respondGzip, RequestDetails theRequestDetails)
|
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
int status = 200;
|
int status = 200;
|
||||||
|
@ -554,12 +553,7 @@ public class RestfulServerUtils {
|
||||||
// Determine response encoding
|
// Determine response encoding
|
||||||
EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails);
|
EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails);
|
||||||
|
|
||||||
String contentType;
|
String contentType = responseEncoding.getBundleContentType();
|
||||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
|
||||||
contentType = responseEncoding.getBrowserFriendlyBundleContentType();
|
|
||||||
} else {
|
|
||||||
contentType = responseEncoding.getBundleContentType();
|
|
||||||
}
|
|
||||||
|
|
||||||
String charset = Constants.CHARSET_NAME_UTF8;
|
String charset = Constants.CHARSET_NAME_UTF8;
|
||||||
Writer writer = theRequestDetails.getResponse().getResponseWriter(status, contentType, charset, respondGzip);
|
Writer writer = theRequestDetails.getResponse().getResponseWriter(status, contentType, charset, respondGzip);
|
||||||
|
@ -577,8 +571,8 @@ public class RestfulServerUtils {
|
||||||
return theRequestDetails.getResponse().sendWriterResponse(status, contentType, charset, writer);
|
return theRequestDetails.getResponse().sendWriterResponse(status, contentType, charset, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, boolean theRequestIsBrowser, Set<SummaryEnum> theSummaryMode,
|
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode,
|
||||||
int stausCode, boolean theRespondGzip, boolean theAddContentLocationHeader, boolean respondGzip,
|
int stausCode, boolean theAddContentLocationHeader, boolean respondGzip,
|
||||||
RequestDetails theRequestDetails)
|
RequestDetails theRequestDetails)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
IRestfulResponse restUtil = theRequestDetails.getResponse();
|
IRestfulResponse restUtil = theRequestDetails.getResponse();
|
||||||
|
@ -637,9 +631,7 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
if (encodingDomainResourceAsText) {
|
||||||
contentType = responseEncoding.getBrowserFriendlyBundleContentType();
|
|
||||||
} else if (encodingDomainResourceAsText) {
|
|
||||||
contentType = Constants.CT_HTML;
|
contentType = Constants.CT_HTML;
|
||||||
} else {
|
} else {
|
||||||
contentType = responseEncoding.getResourceContentType();
|
contentType = responseEncoding.getResourceContentType();
|
||||||
|
@ -668,18 +660,15 @@ public class RestfulServerUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
Writer writer = restUtil.getResponseWriter(stausCode, contentType, charset, respondGzip);
|
Writer writer = restUtil.getResponseWriter(stausCode, contentType, charset, respondGzip);
|
||||||
try {
|
|
||||||
if (encodingDomainResourceAsText && theResource instanceof IResource) {
|
if (encodingDomainResourceAsText && theResource instanceof IResource) {
|
||||||
writer.append(((IResource) theResource).getText().getDiv().getValueAsString());
|
writer.append(((IResource) theResource).getText().getDiv().getValueAsString());
|
||||||
} else {
|
} else {
|
||||||
IParser parser = getNewParser(theServer.getFhirContext(), theRequestDetails);
|
IParser parser = getNewParser(theServer.getFhirContext(), theRequestDetails);
|
||||||
parser.encodeResourceToWriter(theResource, writer);
|
parser.encodeResourceToWriter(theResource, writer);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
//always send a response, even if the parsing went wrong
|
|
||||||
}
|
|
||||||
return restUtil.sendWriterResponse(stausCode, contentType, charset, writer);
|
|
||||||
|
|
||||||
|
return restUtil.sendWriterResponse(stausCode, contentType, charset, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
// static Integer tryToExtractNamedParameter(HttpServletRequest theRequest, String name) {
|
||||||
|
|
|
@ -61,12 +61,12 @@ abstract class BaseValidatingInterceptor<T> extends InterceptorAdapter {
|
||||||
private Integer myAddResponseIssueHeaderOnSeverity = null;
|
private Integer myAddResponseIssueHeaderOnSeverity = null;
|
||||||
private Integer myAddResponseOutcomeHeaderOnSeverity = null;
|
private Integer myAddResponseOutcomeHeaderOnSeverity = null;
|
||||||
private Integer myFailOnSeverity = ResultSeverityEnum.ERROR.ordinal();
|
private Integer myFailOnSeverity = ResultSeverityEnum.ERROR.ordinal();
|
||||||
|
private int myMaximumHeaderLength = 200;
|
||||||
private String myResponseIssueHeaderName = provideDefaultResponseHeaderName();
|
private String myResponseIssueHeaderName = provideDefaultResponseHeaderName();
|
||||||
private String myResponseIssueHeaderValue = DEFAULT_RESPONSE_HEADER_VALUE;
|
private String myResponseIssueHeaderValue = DEFAULT_RESPONSE_HEADER_VALUE;
|
||||||
private String myResponseIssueHeaderValueNoIssues = null;
|
private String myResponseIssueHeaderValueNoIssues = null;
|
||||||
private String myResponseOutcomeHeaderName = provideDefaultResponseHeaderName();
|
private String myResponseOutcomeHeaderName = provideDefaultResponseHeaderName();
|
||||||
private List<IValidatorModule> myValidatorModules;
|
private List<IValidatorModule> myValidatorModules;
|
||||||
|
|
||||||
private void addResponseIssueHeader(RequestDetails theRequestDetails, SingleValidationMessage theNext) {
|
private void addResponseIssueHeader(RequestDetails theRequestDetails, SingleValidationMessage theNext) {
|
||||||
// Perform any string substitutions from the message format
|
// Perform any string substitutions from the message format
|
||||||
StrLookup<?> lookup = new MyLookup(theNext);
|
StrLookup<?> lookup = new MyLookup(theNext);
|
||||||
|
@ -78,7 +78,6 @@ abstract class BaseValidatingInterceptor<T> extends InterceptorAdapter {
|
||||||
|
|
||||||
theRequestDetails.getResponse().addHeader(myResponseIssueHeaderName, headerValue);
|
theRequestDetails.getResponse().addHeader(myResponseIssueHeaderName, headerValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseValidatingInterceptor<T> addValidatorModule(IValidatorModule theModule) {
|
public BaseValidatingInterceptor<T> addValidatorModule(IValidatorModule theModule) {
|
||||||
Validate.notNull(theModule, "theModule must not be null");
|
Validate.notNull(theModule, "theModule must not be null");
|
||||||
if (getValidatorModules() == null) {
|
if (getValidatorModules() == null) {
|
||||||
|
@ -98,6 +97,23 @@ abstract class BaseValidatingInterceptor<T> extends InterceptorAdapter {
|
||||||
throw new UnprocessableEntityException(theRequestDetails.getServer().getFhirContext(), theValidationResult.toOperationOutcome());
|
throw new UnprocessableEntityException(theRequestDetails.getServer().getFhirContext(), theValidationResult.toOperationOutcome());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the validation produces a result with at least the given severity, a header with the name
|
||||||
|
* specified by {@link #setResponseOutcomeHeaderName(String)} will be added containing a JSON encoded
|
||||||
|
* OperationOutcome resource containing the validation results.
|
||||||
|
*/
|
||||||
|
public ResultSeverityEnum getAddResponseOutcomeHeaderOnSeverity() {
|
||||||
|
return myAddResponseOutcomeHeaderOnSeverity != null ? ResultSeverityEnum.values()[myAddResponseOutcomeHeaderOnSeverity] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum length for an individual header. If an individual header would be written exceeding this length,
|
||||||
|
* the header value will be truncated.
|
||||||
|
*/
|
||||||
|
public int getMaximumHeaderLength() {
|
||||||
|
return myMaximumHeaderLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the header specified by {@link #setAddResponseOutcomeHeaderOnSeverity(ResultSeverityEnum)}
|
* The name of the header specified by {@link #setAddResponseOutcomeHeaderOnSeverity(ResultSeverityEnum)}
|
||||||
*/
|
*/
|
||||||
|
@ -109,15 +125,6 @@ abstract class BaseValidatingInterceptor<T> extends InterceptorAdapter {
|
||||||
return myValidatorModules;
|
return myValidatorModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If the validation produces a result with at least the given severity, a header with the name
|
|
||||||
* specified by {@link #setResponseOutcomeHeaderName(String)} will be added containing a JSON encoded
|
|
||||||
* OperationOutcome resource containing the validation results.
|
|
||||||
*/
|
|
||||||
public ResultSeverityEnum getAddResponseOutcomeHeaderOnSeverity() {
|
|
||||||
return myAddResponseOutcomeHeaderOnSeverity != null ? ResultSeverityEnum.values()[myAddResponseOutcomeHeaderOnSeverity] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract String provideDefaultResponseHeaderName();
|
abstract String provideDefaultResponseHeaderName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,6 +155,15 @@ abstract class BaseValidatingInterceptor<T> extends InterceptorAdapter {
|
||||||
myFailOnSeverity = theSeverity != null ? theSeverity.ordinal() : null;
|
myFailOnSeverity = theSeverity != null ? theSeverity.ordinal() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum length for an individual header. If an individual header would be written exceeding this length,
|
||||||
|
* the header value will be truncated. Value must be greater than 100.
|
||||||
|
*/
|
||||||
|
public void setMaximumHeaderLength(int theMaximumHeaderLength) {
|
||||||
|
Validate.isTrue(theMaximumHeaderLength >= 100, "theMaximumHeadeerLength must be >= 100");
|
||||||
|
myMaximumHeaderLength = theMaximumHeaderLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the name of the response header to add validation failures to
|
* Sets the name of the response header to add validation failures to
|
||||||
*
|
*
|
||||||
|
@ -271,6 +287,9 @@ abstract class BaseValidatingInterceptor<T> extends InterceptorAdapter {
|
||||||
if (outcome != null) {
|
if (outcome != null) {
|
||||||
IParser parser = theRequestDetails.getServer().getFhirContext().newJsonParser().setPrettyPrint(false);
|
IParser parser = theRequestDetails.getServer().getFhirContext().newJsonParser().setPrettyPrint(false);
|
||||||
String encoded = parser.encodeResourceToString(outcome);
|
String encoded = parser.encodeResourceToString(outcome);
|
||||||
|
if (encoded.length() > getMaximumHeaderLength()) {
|
||||||
|
encoded = encoded.substring(0, getMaximumHeaderLength() - 3) + "...";
|
||||||
|
}
|
||||||
theRequestDetails.getResponse().addHeader(myResponseOutcomeHeaderName, encoded);
|
theRequestDetails.getResponse().addHeader(myResponseOutcomeHeaderName, encoded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package ca.uhn.fhir.util;
|
package ca.uhn.fhir.util;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
|
@ -37,8 +40,7 @@ public class UrlUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a relative URL - THIS METHOD WILL NOT FAIL but will log a warning and return theEndpoint if the input is
|
* Resolve a relative URL - THIS METHOD WILL NOT FAIL but will log a warning and return theEndpoint if the input is invalid.
|
||||||
* invalid.
|
|
||||||
*/
|
*/
|
||||||
public static String constructAbsoluteUrl(String theBase, String theEndpoint) {
|
public static String constructAbsoluteUrl(String theBase, String theEndpoint) {
|
||||||
if (theEndpoint == null) {
|
if (theEndpoint == null) {
|
||||||
|
@ -174,12 +176,27 @@ public class UrlUtil {
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public static UrlParts parseUrl(String theUrl) {
|
public static UrlParts parseUrl(String theUrl) {
|
||||||
String url = theUrl;
|
String url = theUrl;
|
||||||
if (url.matches("\\/[a-zA-Z]+\\?.*")) {
|
UrlParts retVal = new UrlParts();
|
||||||
|
if (url.startsWith("http")) {
|
||||||
|
if (url.startsWith("/")) {
|
||||||
url = url.substring(1);
|
url = url.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
UrlParts retVal = new UrlParts();
|
int qmIdx = url.indexOf('?');
|
||||||
|
if (qmIdx != -1) {
|
||||||
|
retVal.setParams(defaultIfBlank(url.substring(qmIdx + 1), null));
|
||||||
|
url = url.substring(0, qmIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
IdDt id = new IdDt(url);
|
||||||
|
retVal.setResourceType(id.getResourceType());
|
||||||
|
retVal.setResourceId(id.getIdPart());
|
||||||
|
retVal.setVersionId(id.getVersionIdPart());
|
||||||
|
return retVal;
|
||||||
|
} else {
|
||||||
|
if (url.matches("\\/[a-zA-Z]+\\?.*")) {
|
||||||
|
url = url.substring(1);
|
||||||
|
}
|
||||||
int nextStart = 0;
|
int nextStart = 0;
|
||||||
boolean nextIsHistory = false;
|
boolean nextIsHistory = false;
|
||||||
|
|
||||||
|
@ -214,6 +231,7 @@ public class UrlUtil {
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class UrlParts {
|
public static class UrlParts {
|
||||||
private String myParams;
|
private String myParams;
|
||||||
|
|
|
@ -61,4 +61,8 @@ public class VersionUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
getVersion();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,4 +31,8 @@ public interface INarrative extends ICompositeType {
|
||||||
// TODO: use less broad exception type here
|
// TODO: use less broad exception type here
|
||||||
public String getDivAsString() throws Exception;
|
public String getDivAsString() throws Exception;
|
||||||
|
|
||||||
|
public INarrative setStatusAsString(String theString);
|
||||||
|
|
||||||
|
public String getStatusAsString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationFailedNoId=Failed to {0}
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirDao.transactionOperationFailedUnknownId=Failed to {0} resource in transaction because no resource could be found with ID {1}
|
||||||
|
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionContainsMultipleWithDuplicateId=Transaction bundle contains multiple resources with ID: {0}
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionContainsMultipleWithDuplicateId=Transaction bundle contains multiple resources with ID: {0}
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionEntryHasInvalidVerb=Transaction bundle entry has missing or invalid HTTP Verb specified in Bundle.entry.request.method. Found value: "{0}"
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionEntryHasInvalidVerb=Transaction bundle entry has missing or invalid HTTP Verb specified in Bundle.entry({1}).request.method. Found value: "{0}"
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionMissingUrl=Unable to perform {0}, no URL provided.
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionMissingUrl=Unable to perform {0}, no URL provided.
|
||||||
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
|
ca.uhn.fhir.jpa.dao.BaseHapiFhirSystemDao.transactionInvalidUrl=Unable to perform {0}, URL provided is invalid: {1}
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
<th:block th:switch="${fhirVersion}">
|
<th:block th:switch="${fhirVersion}">
|
||||||
<th:block th:case="'DSTU1'">
|
<th:block th:case="'DSTU1'">
|
||||||
<th:block th:if="${not resource.name.textElement.empty}" th:text="${resource.name.textElement.value}"/>
|
<th:block th:if="${not resource.name.textElement.empty}" th:text="${resource.name.textElement.value}"/>
|
||||||
<th:block th:if=" ${resource.name.textElement.empty} and ${not resource.name.codingFirstRep.displayElement.empty}" th:text="${resource.name.codingFirstRep.display}"/>
|
<th:block th:if=" ${resource.name.textElement.empty} and ${not resource.name.coding[0].displayElement.empty}" th:text="${resource.name.coding[0].display}"/>
|
||||||
<th:block th:if= "${resource.name.textElement.empty} and ${resource.name.codingFirstRep.displayElement.empty}" th:text="Untitled Diagnostic Report"/>
|
<th:block th:if= "${resource.name.textElement.empty} and ${resource.name.coding[0].displayElement.empty}" th:text="Untitled Diagnostic Report"/>
|
||||||
</th:block>
|
</th:block>
|
||||||
<th:block th:case="*">
|
<th:block th:case="*">
|
||||||
<th:block th:if="${not resource.code.textElement.empty}" th:text="${resource.code.textElement.value}"/>
|
<th:block th:if="${not resource.code.textElement.empty} or ${resource.code.coding.empty}" th:text="${resource.code.textElement.value}"/>
|
||||||
<th:block th:if=" ${resource.code.textElement.empty} and ${not resource.code.codingFirstRep.displayElement.empty}" th:text="${resource.code.codingFirstRep.display}"/>
|
<th:block th:if="${not resource.code.coding.empty} and ${resource.code.textElement.empty} and ${not resource.code.coding[0].displayElement.empty}" th:text="${resource.code.coding[0].display}"/>
|
||||||
<th:block th:if= "${resource.code.textElement.empty} and ${resource.code.codingFirstRep.displayElement.empty}" th:text="Untitled Diagnostic Report"/>
|
<th:block th:if="${not resource.code.coding.empty} and ${resource.code.textElement.empty} and ${resource.code.coding[0].displayElement.empty}" th:text="Untitled Diagnostic Report"/>
|
||||||
</th:block>
|
</th:block>
|
||||||
</th:block>
|
</th:block>
|
||||||
<!--/*--> Complete Blood Count <!--*/-->
|
<!--/*--> Complete Blood Count <!--*/-->
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
<td th:narrative="${result.resource.value}">2.2 g/L</td>
|
<td th:narrative="${result.resource.value}">2.2 g/L</td>
|
||||||
<td>
|
<td>
|
||||||
<th:block th:if="${not result.resource.interpretation.textElement.empty}" th:text="${result.resource.interpretation.text}"/>
|
<th:block th:if="${not result.resource.interpretation.textElement.empty}" th:text="${result.resource.interpretation.text}"/>
|
||||||
<th:block th:if="${result.resource.interpretation.textElement.empty} and ${not result.resource.interpretation.codingFirstRep.displayElement.empty}" th:text="${result.resource.interpretation.codingFirstRep.display}"/>
|
<th:block th:if="${result.resource.interpretation.textElement.empty} and ${not result.resource.interpretation.coding.empty} and ${not result.resource.interpretation.coding[0].displayElement.empty}" th:text="${result.resource.interpretation.coding[0].display}"/>
|
||||||
<!--/*--> N <!--*/-->
|
<!--/*--> N <!--*/-->
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -11,16 +11,18 @@ a browser.
|
||||||
<!--*/-->
|
<!--*/-->
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="hapiHeaderText" th:if="${not resource.nameFirstRep.empty}" th:narrative="${resource.nameFirstRep}"/>
|
<th:block th:unless="${#lists.isEmpty(resource.name)}">
|
||||||
|
<div class="hapiHeaderText" th:narrative="${resource.name[0]}"/>
|
||||||
|
</th:block>
|
||||||
<table class="hapiPropertyTable">
|
<table class="hapiPropertyTable">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr th:if="${not resource.identifierFirstRep.empty}">
|
<tr th:if="${not resource.identifier.empty}">
|
||||||
<td>Identifier</td>
|
<td>Identifier</td>
|
||||||
<td th:narrative="${resource.identifierFirstRep}"></td>
|
<td th:narrative="${resource.identifier[0]}"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr th:if="${not resource.addressFirstRep.empty}">
|
<tr th:if="${not resource.address.empty}">
|
||||||
<td>Address</td>
|
<td>Address</td>
|
||||||
<td th:narrative="${resource.addressFirstRep}"></td>
|
<td th:narrative="${resource.address[0]}"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr th:if="${not resource.birthDateElement.empty}">
|
<tr th:if="${not resource.birthDateElement.empty}">
|
||||||
<td>Date of birth</td>
|
<td>Date of birth</td>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<div>
|
<div>
|
||||||
<th:block th:if="${not resource.textElement.empty}" th:text="${resource.textElement.value}"/>
|
<th:block th:if="${not resource.textElement.empty}" th:text="${resource.textElement.value}"/>
|
||||||
<th:block th:if="${resource.textElement.empty}">
|
<th:block th:if="${resource.textElement.empty}">
|
||||||
<th:block th:if="${!resource.codingFirstRep.empty}">
|
<th:block th:if="${!resource.coding.empty}">
|
||||||
<th:block th:if="${!resource.codingFirstRep.displayElement.empty}" th:text="${!resource.codingFirstRep.displayElement.value}"/>
|
<th:block th:if="${!resource.coding[0].displayElement.empty}" th:text="${!resource.coding[0].displayElement.value}"/>
|
||||||
<th:block th:if="${resource.codingFirstRep.displayElement.empty}">
|
<th:block th:if="${resource.coding[0].displayElement.empty}">
|
||||||
<th:block th:if="${!resource.codingFirstRep.codeElement.empty}">
|
<th:block th:if="${!resource.coding[0].codeElement.empty}">
|
||||||
<th:block th:text="${resource.codingFirstRep.codeElement.value}"/>
|
<th:block th:text="${resource.coding[0].codeElement.value}"/>
|
||||||
</th:block>
|
</th:block>
|
||||||
</th:block>
|
</th:block>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<div>
|
<div>
|
||||||
<th:block th:if="${not resource.comparatorElement.empty}" th:text="${resource.comparatorElement.value}"/>
|
<th:block th:if="${not resource.comparatorElement.empty}" th:text="${resource.comparatorElement.value}"/>
|
||||||
<th:block th:if="${not resource.valueElement.empty}" th:text="${resource.valueElement.valueAsString}"/>
|
<th:block th:if="${not resource.valueElement.empty}" th:text="${resource.valueElement.valueAsString}"/>
|
||||||
|
<th:block th:switch="${fhirVersion}">
|
||||||
|
<th:block th:case="'DSTU1'">
|
||||||
<th:block th:if="${not resource.unitsElement.empty}" th:text="${resource.unitsElement.value}"/>
|
<th:block th:if="${not resource.unitsElement.empty}" th:text="${resource.unitsElement.value}"/>
|
||||||
|
</th:block>
|
||||||
|
<th:block th:case="*">
|
||||||
|
<th:block th:if="${not resource.unitElement.empty}" th:text="${resource.unitElement.value}"/>
|
||||||
|
</th:block>
|
||||||
|
</th:block>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
<div>
|
<div>
|
||||||
<th:block th:if="${not resource.valueElement.empty}" th:text="${resource.valueElement.valueAsString}"/>
|
<th:block th:if="${not resource.valueElement.empty}" th:text="${resource.valueElement.valueAsString}"/>
|
||||||
|
<th:block th:switch="${fhirVersion}">
|
||||||
|
<th:block th:case="'DSTU1'">
|
||||||
<th:block th:if="${not resource.unitsElement.empty}" th:text="${resource.unitsElement.value}"/>
|
<th:block th:if="${not resource.unitsElement.empty}" th:text="${resource.unitsElement.value}"/>
|
||||||
|
</th:block>
|
||||||
|
<th:block th:case="*">
|
||||||
|
<th:block th:if="${not resource.unitElement.empty}" th:text="${resource.unitElement.value}"/>
|
||||||
|
</th:block>
|
||||||
|
</th:block>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -48,25 +48,19 @@ simplequantity.narrative=classpath:ca/uhn/fhir/narrative/datatype/SimpleQuantity
|
||||||
|
|
||||||
diagnosticreport.class=ca.uhn.fhir.model.dstu.resource.DiagnosticReport
|
diagnosticreport.class=ca.uhn.fhir.model.dstu.resource.DiagnosticReport
|
||||||
diagnosticreport.narrative=classpath:ca/uhn/fhir/narrative/DiagnosticReport.html
|
diagnosticreport.narrative=classpath:ca/uhn/fhir/narrative/DiagnosticReport.html
|
||||||
diagnosticreport.title=classpath:ca/uhn/fhir/narrative/title/DiagnosticReport.html
|
|
||||||
|
|
||||||
encounter.class=ca.uhn.fhir.model.dstu.resource.Encounter
|
encounter.class=ca.uhn.fhir.model.dstu.resource.Encounter
|
||||||
encounter.title=classpath:ca/uhn/fhir/narrative/title/Encounter.html
|
|
||||||
|
|
||||||
operationoutcome.class=ca.uhn.fhir.model.dstu.resource.OperationOutcome
|
operationoutcome.class=ca.uhn.fhir.model.dstu.resource.OperationOutcome
|
||||||
operationoutcome.title=classpath:ca/uhn/fhir/narrative/title/OperationOutcome.html
|
|
||||||
operationoutcome.narrative=classpath:ca/uhn/fhir/narrative/OperationOutcome.html
|
operationoutcome.narrative=classpath:ca/uhn/fhir/narrative/OperationOutcome.html
|
||||||
|
|
||||||
organization.class=ca.uhn.fhir.model.dstu.resource.Organization
|
organization.class=ca.uhn.fhir.model.dstu.resource.Organization
|
||||||
organization.title=classpath:ca/uhn/fhir/narrative/title/Organization.html
|
|
||||||
|
|
||||||
patient.class=ca.uhn.fhir.model.dstu.resource.Patient
|
patient.class=ca.uhn.fhir.model.dstu.resource.Patient
|
||||||
patient.narrative=classpath:ca/uhn/fhir/narrative/Patient.html
|
patient.narrative=classpath:ca/uhn/fhir/narrative/Patient.html
|
||||||
patient.title=classpath:ca/uhn/fhir/narrative/title/Patient.html
|
|
||||||
|
|
||||||
medicationprescription.class=ca.uhn.fhir.model.dstu.resource.MedicationPrescription
|
medicationprescription.class=ca.uhn.fhir.model.dstu.resource.MedicationPrescription
|
||||||
medicationprescription.narrative=classpath:ca/uhn/fhir/narrative/MedicationPrescription.html
|
medicationprescription.narrative=classpath:ca/uhn/fhir/narrative/MedicationPrescription.html
|
||||||
medicationprescription.title=classpath:ca/uhn/fhir/narrative/title/MedicationPrescription.html
|
|
||||||
|
|
||||||
medication.class=ca.uhn.fhir.model.dstu.resource.Medication
|
medication.class=ca.uhn.fhir.model.dstu.resource.Medication
|
||||||
medication.narrative=classpath:ca/uhn/fhir/narrative/Medication.html
|
medication.narrative=classpath:ca/uhn/fhir/narrative/Medication.html
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
<div>
|
|
||||||
<th:block th:switch="${fhirVersion}">
|
|
||||||
<th:block th:case="'DSTU1'">
|
|
||||||
<th:block th:if="${not resource.name.textElement.empty}" th:text="${resource.name.textElement.value}"/>
|
|
||||||
<th:block th:if=" ${resource.name.textElement.empty} and ${not resource.name.codingFirstRep.displayElement.empty}" th:text="${resource.name.codingFirstRep.display}"/>
|
|
||||||
<th:block th:if= "${resource.name.textElement.empty} and ${resource.name.codingFirstRep.displayElement.empty}" th:text="Untitled Diagnostic Report"/>
|
|
||||||
</th:block>
|
|
||||||
<th:block th:case="*">
|
|
||||||
<th:block th:if="${not resource.code.textElement.empty}" th:text="${resource.code.textElement.value}"/>
|
|
||||||
<th:block th:if=" ${resource.code.textElement.empty} and ${not resource.code.codingFirstRep.displayElement.empty}" th:text="${resource.code.codingFirstRep.display}"/>
|
|
||||||
<th:block th:if= "${resource.code.textElement.empty} and ${resource.code.codingFirstRep.displayElement.empty}" th:text="Untitled Diagnostic Report"/>
|
|
||||||
</th:block>
|
|
||||||
</th:block>
|
|
||||||
<th:block th:if="${not resource.statusElement.empty}" th:text="' - ' + ${resource.statusElement.value}"/>
|
|
||||||
<th:block th:text="' - ' + ${resource.result.size} + ' observations'"/>
|
|
||||||
|
|
||||||
</div>
|
|
|
@ -1,15 +0,0 @@
|
||||||
<div>
|
|
||||||
<th:block th:if="${!resource.identifierFirstRep.empty}" th:narrative="${resource.identifierFirstRep}" />
|
|
||||||
<th:block th:if="${not resource.statusElement.empty}">
|
|
||||||
/ <th:block th:narrative="${resource.statusElement}"/>
|
|
||||||
</th:block>
|
|
||||||
<th:block th:if="${not resource.typeFirstRep.empty}">
|
|
||||||
/ <th:block th:narrative="${resource.typeFirstRep}"/>
|
|
||||||
</th:block>
|
|
||||||
<th:block th:if="${not resource.classElementElement.empty}">
|
|
||||||
/ <th:block th:narrative="${resource.classElementElement}"/>
|
|
||||||
</th:block>
|
|
||||||
<th:block th:if="${not resource.period.empty}">
|
|
||||||
/ <th:block th:narrative="${resource.period}"/>
|
|
||||||
</th:block>
|
|
||||||
</div>
|
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<div class="hapiHeaderText" th:if="${not resource.medication.resource.nameElement.empty}" th:narrative="${resource.medication.resource.nameElement}"></div>
|
|
||||||
</div>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<div>
|
|
||||||
Operation Outcome
|
|
||||||
<th:block th:if="${resource.issue.size} == 1" th:text="'(' + ${resource.issueFirstRep.severityElement.value} + ')'"/>
|
|
||||||
<th:block th:if="${resource.issue.size} != 1" th:text="'(' + ${resource.issue.size} + ' issues)'"/>
|
|
||||||
</div>
|
|
|
@ -1,4 +0,0 @@
|
||||||
<div>
|
|
||||||
<th:block th:if="${not resource.nameElement.empty}" th:text="${resource.nameElement.value}"/>
|
|
||||||
<th:block th:if="${resource.nameElement.empty}">Unknown Organization</th:block>
|
|
||||||
</div>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<div>
|
|
||||||
<th:block th:narrative="${resource.nameFirstRep}" />
|
|
||||||
<th:block th:if="${not resource.identifierFirstRep.empty}">
|
|
||||||
(<th:block th:narrative="${resource.identifierFirstRep}">8708660</th:block>)
|
|
||||||
</th:block>
|
|
||||||
</div>
|
|
|
@ -4,6 +4,8 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.util.UrlUtil.UrlParts;
|
||||||
|
|
||||||
public class UrlUtilTest {
|
public class UrlUtilTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -23,6 +25,18 @@ public class UrlUtilTest {
|
||||||
assertFalse(UrlUtil.isValid(null));
|
assertFalse(UrlUtil.isValid(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseUrl() {
|
||||||
|
assertEquals("ConceptMap", UrlUtil.parseUrl("http://hl7.org/fhir/ConceptMap/ussgfht-loincde").getResourceType());
|
||||||
|
assertEquals("ConceptMap", UrlUtil.parseUrl("http://hl7.org/fhir/ConceptMap/ussgfht-loincde").getResourceType());
|
||||||
|
assertEquals("ussgfht-loincde", UrlUtil.parseUrl("http://hl7.org/fhir/ConceptMap/ussgfht-loincde").getResourceId());
|
||||||
|
assertEquals(null, UrlUtil.parseUrl("http://hl7.org/fhir/ConceptMap/ussgfht-loincde?").getParams());
|
||||||
|
assertEquals("a=b", UrlUtil.parseUrl("http://hl7.org/fhir/ConceptMap/ussgfht-loincde?a=b").getParams());
|
||||||
|
|
||||||
|
assertEquals("a=b", UrlUtil.parseUrl("ConceptMap/ussgfht-loincde?a=b").getParams());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstructAbsoluteUrl() {
|
public void testConstructAbsoluteUrl() {
|
||||||
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl(null, "http://foo/bar/baz"));
|
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl(null, "http://foo/bar/baz"));
|
||||||
|
|
|
@ -18,7 +18,6 @@ import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
|
import ca.uhn.fhir.model.dstu2.resource.StructureDefinition;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
import ca.uhn.fhir.model.dstu2.resource.ValueSet;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
|
||||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||||
|
|
||||||
public class ValidationDataUploader extends BaseCommand {
|
public class ValidationDataUploader extends BaseCommand {
|
||||||
|
@ -64,7 +63,8 @@ public class ValidationDataUploader extends BaseCommand {
|
||||||
|
|
||||||
String vsContents;
|
String vsContents;
|
||||||
try {
|
try {
|
||||||
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/valuesets.xml"), "UTF-8");
|
ctx.getVersion().getPathToSchemaDefinitions();
|
||||||
|
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/"+"valuesets.xml"), "UTF-8");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandFailureException(e.toString());
|
throw new CommandFailureException(e.toString());
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ public class ValidationDataUploader extends BaseCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v3-codesystems.xml"), "UTF-8");
|
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/"+"v3-codesystems.xml"), "UTF-8");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandFailureException(e.toString());
|
throw new CommandFailureException(e.toString());
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ public class ValidationDataUploader extends BaseCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/v2-tables.xml"), "UTF-8");
|
vsContents = IOUtils.toString(ValidationDataUploader.class.getResourceAsStream("/org/hl7/fhir/instance/model/valueset/"+"v2-tables.xml"), "UTF-8");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandFailureException(e.toString());
|
throw new CommandFailureException(e.toString());
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ public class ValidationDataUploader extends BaseCommand {
|
||||||
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
|
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
|
||||||
Resource[] mappingLocations;
|
Resource[] mappingLocations;
|
||||||
try {
|
try {
|
||||||
mappingLocations = patternResolver.getResources("classpath*:org/hl7/fhir/instance/model/profile/*.profile.xml");
|
mappingLocations = patternResolver.getResources("classpath*:org/hl7/fhir/instance/model/profile/"+"*.profile.xml");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CommandFailureException(e.toString());
|
throw new CommandFailureException(e.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,24 +45,13 @@ public class JaxRsResponseTest {
|
||||||
boolean theRequestIsBrowser = false;
|
boolean theRequestIsBrowser = false;
|
||||||
boolean respondGzip = false;
|
boolean respondGzip = false;
|
||||||
Set<SummaryEnum> theSummaryMode = Collections.<SummaryEnum>emptySet();
|
Set<SummaryEnum> theSummaryMode = Collections.<SummaryEnum>emptySet();
|
||||||
Response result = (Response) RestfulServerUtils.streamResponseAsBundle(request.getServer(), bundle, theSummaryMode, theRequestIsBrowser, respondGzip, request);
|
Response result = (Response) RestfulServerUtils.streamResponseAsBundle(request.getServer(), bundle, theSummaryMode, respondGzip, request);
|
||||||
assertEquals(200, result.getStatus());
|
assertEquals(200, result.getStatus());
|
||||||
assertEquals(Constants.CT_FHIR_JSON+Constants.CHARSET_UTF8_CTSUFFIX, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
assertEquals(Constants.CT_FHIR_JSON+Constants.CHARSET_UTF8_CTSUFFIX, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
assertTrue(result.getEntity().toString().contains("Patient"));
|
assertTrue(result.getEntity().toString().contains("Patient"));
|
||||||
assertTrue(result.getEntity().toString().contains("15"));
|
assertTrue(result.getEntity().toString().contains("15"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetResponseWriterBrowserNoZip() throws IOException {
|
|
||||||
boolean theRequestIsBrowser = true;
|
|
||||||
boolean respondGzip = false;
|
|
||||||
Response result = (Response) RestfulServerUtils.streamResponseAsBundle(request.getServer(), bundle, theSummaryMode, theRequestIsBrowser, respondGzip, request);
|
|
||||||
assertEquals(200, result.getStatus());
|
|
||||||
assertEquals(Constants.CT_JSON+Constants.CHARSET_UTF8_CTSUFFIX, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
|
||||||
assertTrue(result.getEntity().toString().contains("Patient"));
|
|
||||||
assertTrue(result.getEntity().toString().contains("15"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSendAttachmentResponse() throws IOException {
|
public void testSendAttachmentResponse() throws IOException {
|
||||||
boolean theRequestIsBrowser = true;
|
boolean theRequestIsBrowser = true;
|
||||||
|
@ -73,7 +62,7 @@ public class JaxRsResponseTest {
|
||||||
binary.setContentType(contentType);
|
binary.setContentType(contentType);
|
||||||
binary.setContent(content);
|
binary.setContent(content);
|
||||||
boolean theAddContentLocationHeader = false;
|
boolean theAddContentLocationHeader = false;
|
||||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theRequestIsBrowser, theSummaryMode, 200, respondGzip, theAddContentLocationHeader, respondGzip, this.request);
|
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theSummaryMode, 200, theAddContentLocationHeader, respondGzip, this.request);
|
||||||
assertEquals(200, result.getStatus());
|
assertEquals(200, result.getStatus());
|
||||||
assertEquals(contentType, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
assertEquals(contentType, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
assertEquals(content, result.getEntity());
|
assertEquals(content, result.getEntity());
|
||||||
|
@ -86,7 +75,7 @@ public class JaxRsResponseTest {
|
||||||
IBaseBinary binary = new Binary();
|
IBaseBinary binary = new Binary();
|
||||||
binary.setContent(new byte[]{});
|
binary.setContent(new byte[]{});
|
||||||
boolean theAddContentLocationHeader = false;
|
boolean theAddContentLocationHeader = false;
|
||||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theRequestIsBrowser, theSummaryMode, 200, respondGzip, theAddContentLocationHeader, respondGzip, this.request);
|
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theSummaryMode, 200, theAddContentLocationHeader, respondGzip, this.request);
|
||||||
assertEquals(200, result.getStatus());
|
assertEquals(200, result.getStatus());
|
||||||
assertEquals(null, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
assertEquals(null, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
assertEquals(null, result.getEntity());
|
assertEquals(null, result.getEntity());
|
||||||
|
@ -98,7 +87,7 @@ public class JaxRsResponseTest {
|
||||||
boolean respondGzip = true;
|
boolean respondGzip = true;
|
||||||
IBaseBinary binary = new Binary();
|
IBaseBinary binary = new Binary();
|
||||||
boolean theAddContentLocationHeader = false;
|
boolean theAddContentLocationHeader = false;
|
||||||
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theRequestIsBrowser, theSummaryMode, 200, respondGzip, theAddContentLocationHeader, respondGzip, this.request);
|
Response result = (Response) RestfulServerUtils.streamResponseAsResource(request.getServer(), binary, theSummaryMode, 200, theAddContentLocationHeader, respondGzip, this.request);
|
||||||
assertEquals(200, result.getStatus());
|
assertEquals(200, result.getStatus());
|
||||||
assertEquals(null, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
assertEquals(null, result.getHeaderString(Constants.HEADER_CONTENT_TYPE));
|
||||||
assertEquals(null, result.getEntity());
|
assertEquals(null, result.getEntity());
|
||||||
|
|
|
@ -225,7 +225,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.transaction</groupId>
|
<groupId>javax.transaction</groupId>
|
||||||
<artifactId>jta</artifactId>
|
<artifactId>javax.transaction-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.mail</groupId>
|
<groupId>javax.mail</groupId>
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class BaseDstu21Config extends BaseConfig {
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(autowire=Autowire.BY_NAME)
|
@Bean(autowire=Autowire.BY_NAME, name="myJpaValidationSupportChainDstu21")
|
||||||
public IValidationSupport validationSupportChainDstu21() {
|
public IValidationSupport validationSupportChainDstu21() {
|
||||||
return new JpaValidationSupportChainDstu21();
|
return new JpaValidationSupportChainDstu21();
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,6 +355,9 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
||||||
nextEntity = new ResourceLink(nextPath, theEntity, target);
|
nextEntity = new ResourceLink(nextPath, theEntity, target);
|
||||||
} else {
|
} else {
|
||||||
if (!multiType) {
|
if (!multiType) {
|
||||||
|
if (nextSpDef.getName().equals("sourceuri")) {
|
||||||
|
continue; // TODO: disable this eventually - ConceptMap:sourceuri is of type reference but points to a URI
|
||||||
|
}
|
||||||
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
throw new ConfigurationException("Search param " + nextSpDef.getName() + " is of unexpected datatype: " + nextObject.getClass());
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -292,6 +292,15 @@ public class FhirSystemDaoDstu21 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
Map<IdType, IdType> idSubstitutions = new HashMap<IdType, IdType>();
|
Map<IdType, IdType> idSubstitutions = new HashMap<IdType, IdType>();
|
||||||
Map<IdType, DaoMethodOutcome> idToPersistedOutcome = new HashMap<IdType, DaoMethodOutcome>();
|
Map<IdType, DaoMethodOutcome> idToPersistedOutcome = new HashMap<IdType, DaoMethodOutcome>();
|
||||||
|
|
||||||
|
// Do all entries have a verb?
|
||||||
|
for (int i = 0; i < theRequest.getEntry().size(); i++) {
|
||||||
|
BundleEntryComponent nextReqEntry = theRequest.getEntry().get(i);
|
||||||
|
HTTPVerb verb = nextReqEntry.getRequest().getMethodElement().getValue();
|
||||||
|
if (verb == null) {
|
||||||
|
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionEntryHasInvalidVerb", nextReqEntry.getRequest().getMethod(), i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to execute the transaction request bundle elements in the order
|
* We want to execute the transaction request bundle elements in the order
|
||||||
* specified by the FHIR specification (see TransactionSorter) so we save the
|
* specified by the FHIR specification (see TransactionSorter) so we save the
|
||||||
|
@ -366,9 +375,6 @@ public class FhirSystemDaoDstu21 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPVerb verb = nextReqEntry.getRequest().getMethodElement().getValue();
|
HTTPVerb verb = nextReqEntry.getRequest().getMethodElement().getValue();
|
||||||
if (verb == null) {
|
|
||||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseHapiFhirSystemDao.class, "transactionEntryHasInvalidVerb", nextReqEntry.getRequest().getMethod()));
|
|
||||||
}
|
|
||||||
|
|
||||||
String resourceType = res != null ? getContext().getResourceDefinition(res).getName() : null;
|
String resourceType = res != null ? getContext().getResourceDefinition(res).getName() : null;
|
||||||
BundleEntryComponent nextRespEntry = response.getEntry().get(originalRequestOrder.get(nextReqEntry));
|
BundleEntryComponent nextRespEntry = response.getEntry().get(originalRequestOrder.get(nextReqEntry));
|
||||||
|
|
|
@ -9,6 +9,8 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
public class JpaValidationSupportChainDstu21 extends ValidationSupportChain {
|
public class JpaValidationSupportChainDstu21 extends ValidationSupportChain {
|
||||||
|
|
||||||
|
private DefaultProfileValidationSupport myDefaultProfileValidationSupport = new DefaultProfileValidationSupport();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier("myJpaValidationSupportDstu21")
|
@Qualifier("myJpaValidationSupportDstu21")
|
||||||
public ca.uhn.fhir.jpa.dao.IJpaValidationSupportDstu21 myJpaValidationSupportDstu21;
|
public ca.uhn.fhir.jpa.dao.IJpaValidationSupportDstu21 myJpaValidationSupportDstu21;
|
||||||
|
@ -17,15 +19,13 @@ public class JpaValidationSupportChainDstu21 extends ValidationSupportChain {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DefaultProfileValidationSupport myDefaultProfileValidationSupport = new DefaultProfileValidationSupport();
|
public void flush() {
|
||||||
|
myDefaultProfileValidationSupport.flush();
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void postConstruct() {
|
public void postConstruct() {
|
||||||
addValidationSupport(myDefaultProfileValidationSupport);
|
addValidationSupport(myDefaultProfileValidationSupport);
|
||||||
addValidationSupport(myJpaValidationSupportDstu21);
|
addValidationSupport(myJpaValidationSupportDstu21);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() {
|
|
||||||
myDefaultProfileValidationSupport.flush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import javax.persistence.EntityManager;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hibernate.search.jpa.FullTextEntityManager;
|
import org.hibernate.search.jpa.FullTextEntityManager;
|
||||||
import org.hibernate.search.jpa.Search;
|
import org.hibernate.search.jpa.Search;
|
||||||
|
import org.hl7.fhir.dstu21.hapi.validation.IValidationSupport;
|
||||||
import org.hl7.fhir.dstu21.model.Bundle;
|
import org.hl7.fhir.dstu21.model.Bundle;
|
||||||
import org.hl7.fhir.dstu21.model.CodeableConcept;
|
import org.hl7.fhir.dstu21.model.CodeableConcept;
|
||||||
import org.hl7.fhir.dstu21.model.Coding;
|
import org.hl7.fhir.dstu21.model.Coding;
|
||||||
|
@ -86,7 +87,9 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
||||||
@ContextConfiguration(classes= {TestDstu21Config.class})
|
@ContextConfiguration(classes= {TestDstu21Config.class})
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public abstract class BaseJpaDstu21Test extends BaseJpaTest {
|
public abstract class BaseJpaDstu21Test extends BaseJpaTest {
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("myJpaValidationSupportChainDstu21")
|
||||||
|
protected IValidationSupport myValidationSupport;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected ApplicationContext myAppCtx;
|
protected ApplicationContext myAppCtx;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -875,6 +875,43 @@ public class FhirSystemDaoDstu21Test extends BaseJpaDstu21SystemTest {
|
||||||
assertEquals("Patient/temp6789", p.getLink().get(0).getOther().getReference());
|
assertEquals("Patient/temp6789", p.getLink().get(0).getOther().getReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithBundledValidationSourceAndTarget() throws Exception {
|
||||||
|
|
||||||
|
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/questionnaire-sdc-profile-example-ussg-fht.xml");
|
||||||
|
String bundleStr = IOUtils.toString(bundleRes);
|
||||||
|
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, bundleStr);
|
||||||
|
|
||||||
|
Bundle resp = mySystemDao.transaction(myRequestDetails, bundle);
|
||||||
|
|
||||||
|
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
encoded = myFhirCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(resp);
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(encoded, containsString("\"response\":{" +
|
||||||
|
"\"status\":\"201 Created\"," +
|
||||||
|
"\"location\":\"Questionnaire/54127-6/_history/1\","));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Upload again to update
|
||||||
|
*/
|
||||||
|
|
||||||
|
resp = mySystemDao.transaction(myRequestDetails, bundle);
|
||||||
|
|
||||||
|
encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(resp);
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
encoded = myFhirCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(resp);
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(encoded, containsString("\"response\":{" +
|
||||||
|
"\"status\":\"200 OK\"," +
|
||||||
|
"\"location\":\"Questionnaire/54127-6/_history/2\","));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionFromBundle6() throws Exception {
|
public void testTransactionFromBundle6() throws Exception {
|
||||||
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
|
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/simone_bundle3.xml");
|
||||||
|
|
|
@ -13,18 +13,24 @@ import java.io.InputStream;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.http.Header;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.dstu21.model.Bundle;
|
import org.hl7.fhir.dstu21.model.Bundle;
|
||||||
import org.hl7.fhir.dstu21.model.Bundle.BundleType;
|
import org.hl7.fhir.dstu21.model.Bundle.BundleType;
|
||||||
import org.hl7.fhir.dstu21.model.Bundle.HTTPVerb;
|
import org.hl7.fhir.dstu21.model.Bundle.HTTPVerb;
|
||||||
import org.hl7.fhir.dstu21.model.DecimalType;
|
import org.hl7.fhir.dstu21.model.DecimalType;
|
||||||
|
import org.hl7.fhir.dstu21.model.Enumerations.AdministrativeGender;
|
||||||
import org.hl7.fhir.dstu21.model.IdType;
|
import org.hl7.fhir.dstu21.model.IdType;
|
||||||
import org.hl7.fhir.dstu21.model.Observation;
|
import org.hl7.fhir.dstu21.model.Observation;
|
||||||
import org.hl7.fhir.dstu21.model.OperationDefinition;
|
import org.hl7.fhir.dstu21.model.OperationDefinition;
|
||||||
|
@ -33,6 +39,7 @@ import org.hl7.fhir.dstu21.model.Parameters;
|
||||||
import org.hl7.fhir.dstu21.model.Patient;
|
import org.hl7.fhir.dstu21.model.Patient;
|
||||||
import org.hl7.fhir.dstu21.model.StringType;
|
import org.hl7.fhir.dstu21.model.StringType;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -41,16 +48,20 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.dao.dstu21.BaseJpaDstu21Test;
|
import ca.uhn.fhir.jpa.dao.dstu21.BaseJpaDstu21Test;
|
||||||
|
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||||
import ca.uhn.fhir.jpa.rp.dstu21.ObservationResourceProvider;
|
import ca.uhn.fhir.jpa.rp.dstu21.ObservationResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.rp.dstu21.OrganizationResourceProvider;
|
import ca.uhn.fhir.jpa.rp.dstu21.OrganizationResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.rp.dstu21.PatientResourceProvider;
|
import ca.uhn.fhir.jpa.rp.dstu21.PatientResourceProvider;
|
||||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor;
|
||||||
|
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||||
|
|
||||||
public class SystemProviderDstu21Test extends BaseJpaDstu21Test {
|
public class SystemProviderDstu21Test extends BaseJpaDstu21Test {
|
||||||
|
|
||||||
|
@ -113,6 +124,62 @@ public class SystemProviderDstu21Test extends BaseJpaDstu21Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@After
|
||||||
|
public void after() {
|
||||||
|
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Test
|
||||||
|
public void testResponseUsesCorrectContentType() throws Exception {
|
||||||
|
myRestServer.setUseBrowserFriendlyContentTypes(true);
|
||||||
|
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||||
|
|
||||||
|
HttpGet get = new HttpGet(ourServerBase);
|
||||||
|
// get.addHeader("Accept", "application/xml, text/html");
|
||||||
|
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||||
|
assertThat(http.getFirstHeader("Content-Type").getValue(), containsString("application/json+fhir"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateUsingIncomingResources() throws Exception {
|
||||||
|
FhirInstanceValidator val = new FhirInstanceValidator(myValidationSupport);
|
||||||
|
RequestValidatingInterceptor interceptor = new RequestValidatingInterceptor();
|
||||||
|
interceptor.addValidatorModule(val);
|
||||||
|
interceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||||
|
interceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||||
|
myRestServer.registerInterceptor(interceptor);
|
||||||
|
try {
|
||||||
|
|
||||||
|
InputStream bundleRes = SystemProviderDstu2Test.class.getResourceAsStream("/questionnaire-sdc-profile-example-ussg-fht.xml");
|
||||||
|
String bundleStr = IOUtils.toString(bundleRes);
|
||||||
|
|
||||||
|
HttpPost req = new HttpPost(ourServerBase);
|
||||||
|
req.setEntity(new StringEntity(bundleStr, ContentType.parse(Constants.CT_FHIR_XML + "; charset=utf-8")));
|
||||||
|
|
||||||
|
CloseableHttpResponse resp = ourHttpClient.execute(req);
|
||||||
|
|
||||||
|
String encoded = IOUtils.toString(resp.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(resp.getEntity().getContent());
|
||||||
|
ourLog.info(encoded);
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
assertThat(encoded, containsString("Questionnaire/54127-6/_history/"));
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
for (Header next : resp.getHeaders(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_NAME)) {
|
||||||
|
ourLog.info(next.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
myRestServer.unregisterInterceptor(interceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEverythingReturnsCorrectFormatInPagingLink() throws Exception {
|
public void testEverythingReturnsCorrectFormatInPagingLink() throws Exception {
|
||||||
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
|
myRestServer.setDefaultResponseEncoding(EncodingEnum.JSON);
|
||||||
|
@ -129,6 +196,7 @@ public class SystemProviderDstu21Test extends BaseJpaDstu21Test {
|
||||||
HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything");
|
HttpGet get = new HttpGet(ourServerBase + "/Patient/$everything");
|
||||||
get.addHeader("Accept", "application/xml, text/html");
|
get.addHeader("Accept", "application/xml, text/html");
|
||||||
CloseableHttpResponse http = ourHttpClient.execute(get);
|
CloseableHttpResponse http = ourHttpClient.execute(get);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String response = IOUtils.toString(http.getEntity().getContent());
|
String response = IOUtils.toString(http.getEntity().getContent());
|
||||||
ourLog.info(response);
|
ourLog.info(response);
|
||||||
|
@ -282,6 +350,23 @@ public class SystemProviderDstu21Test extends BaseJpaDstu21Test {
|
||||||
ourLog.info(response);
|
ourLog.info(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactionWithIncompleteBundle() throws Exception {
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
|
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.setType(BundleType.TRANSACTION);
|
||||||
|
bundle.addEntry().setResource(patient);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ourClient.transaction().withBundle(bundle).prettyPrint().execute();
|
||||||
|
fail();
|
||||||
|
} catch (InvalidRequestException e) {
|
||||||
|
assertThat(e.toString(), containsString(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionFromBundle2() throws Exception {
|
public void testTransactionFromBundle2() throws Exception {
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -126,20 +126,6 @@ public class JpaServerDemo extends RestfulServer {
|
||||||
FhirContext ctx = getFhirContext();
|
FhirContext ctx = getFhirContext();
|
||||||
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
ctx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
||||||
|
|
||||||
/*
|
|
||||||
* This tells the server to use "browser friendly" MIME types if it
|
|
||||||
* detects that the request is coming from a browser, in the hopes that the
|
|
||||||
* browser won't just treat the content as a binary payload and try
|
|
||||||
* to download it (which is what generally happens if you load a
|
|
||||||
* FHIR URL in a browser).
|
|
||||||
*
|
|
||||||
* This means that the server isn't technically complying with the
|
|
||||||
* FHIR specification for direct browser requests, but this mode
|
|
||||||
* is very helpful for testing and troubleshooting since it means
|
|
||||||
* you can look at FHIR URLs directly in a browser.
|
|
||||||
*/
|
|
||||||
setUseBrowserFriendlyContentTypes(true);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default to XML and pretty printing
|
* Default to XML and pretty printing
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -61,7 +61,6 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
myContext = theContext;
|
myContext = theContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
|
public void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes) {
|
||||||
if (myBundle == null) {
|
if (myBundle == null) {
|
||||||
|
@ -78,7 +77,7 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IBaseResource nextBaseRes : theResult) {
|
for (IBaseResource nextBaseRes : theResult) {
|
||||||
IResource next = (IResource)nextBaseRes;
|
IResource next = (IResource) nextBaseRes;
|
||||||
|
|
||||||
Set<String> containedIds = new HashSet<String>();
|
Set<String> containedIds = new HashSet<String>();
|
||||||
for (IResource nextContained : next.getContained().getContainedResources()) {
|
for (IResource nextContained : next.getContained().getContainedResources()) {
|
||||||
|
@ -87,16 +86,6 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myContext.getNarrativeGenerator() != null) {
|
|
||||||
String title = myContext.getNarrativeGenerator().generateTitle(next);
|
|
||||||
ourLog.trace("Narrative generator created title: {}", title);
|
|
||||||
if (StringUtils.isNotBlank(title)) {
|
|
||||||
ResourceMetadataKeyEnum.TITLE.put(next, title);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ourLog.trace("No narrative generator specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ResourceReferenceInfo> references = myContext.newTerser().getAllResourceReferences(next);
|
List<ResourceReferenceInfo> references = myContext.newTerser().getAllResourceReferences(next);
|
||||||
do {
|
do {
|
||||||
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
|
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
|
||||||
|
@ -197,7 +186,8 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeBundleFromBundleProvider(IRestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
public void initializeBundleFromBundleProvider(IRestfulServer theServer, IBundleProvider theResult, EncodingEnum theResponseEncoding, String theServerBase, String theCompleteUrl,
|
||||||
|
boolean thePrettyPrint, int theOffset, Integer theLimit, String theSearchId, BundleTypeEnum theBundleType, Set<Include> theIncludes) {
|
||||||
int numToReturn;
|
int numToReturn;
|
||||||
String searchId = null;
|
String searchId = null;
|
||||||
List<IBaseResource> resourceList;
|
List<IBaseResource> resourceList;
|
||||||
|
@ -255,7 +245,8 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
|
|
||||||
if (searchId != null) {
|
if (searchId != null) {
|
||||||
if (theOffset + numToReturn < theResult.size()) {
|
if (theOffset + numToReturn < theResult.size()) {
|
||||||
myBundle.getLinkNext().setValue(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint, theBundleType));
|
myBundle.getLinkNext()
|
||||||
|
.setValue(RestfulServerUtils.createPagingLink(theIncludes, theServerBase, searchId, theOffset + numToReturn, numToReturn, theResponseEncoding, thePrettyPrint, theBundleType));
|
||||||
}
|
}
|
||||||
if (theOffset > 0) {
|
if (theOffset > 0) {
|
||||||
int start = Math.max(0, theOffset - limit);
|
int start = Math.max(0, theOffset - limit);
|
||||||
|
@ -266,7 +257,8 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults, BundleTypeEnum theBundleType) {
|
public void initializeBundleFromResourceList(String theAuthor, List<? extends IBaseResource> theResult, String theServerBase, String theCompleteUrl, int theTotalResults,
|
||||||
|
BundleTypeEnum theBundleType) {
|
||||||
myBundle = new Bundle();
|
myBundle = new Bundle();
|
||||||
|
|
||||||
myBundle.getAuthorName().setValue(theAuthor);
|
myBundle.getAuthorName().setValue(theAuthor);
|
||||||
|
@ -294,16 +286,6 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myContext.getNarrativeGenerator() != null) {
|
|
||||||
String title = myContext.getNarrativeGenerator().generateTitle(next);
|
|
||||||
ourLog.trace("Narrative generator created title: {}", title);
|
|
||||||
if (StringUtils.isNotBlank(title)) {
|
|
||||||
ResourceMetadataKeyEnum.TITLE.put(next, title);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ourLog.trace("No narrative generator specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BaseResourceReferenceDt> references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
|
List<BaseResourceReferenceDt> references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
|
||||||
do {
|
do {
|
||||||
List<IBaseResource> addedResourcesThisPass = new ArrayList<IBaseResource>();
|
List<IBaseResource> addedResourcesThisPass = new ArrayList<IBaseResource>();
|
||||||
|
@ -367,10 +349,9 @@ public class Dstu1BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
throw new UnsupportedOperationException("DSTU1 server doesn't support resource style bundles");
|
throw new UnsupportedOperationException("DSTU1 server doesn't support resource style bundles");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<IBaseResource> toListOfResources() {
|
public List<IBaseResource> toListOfResources() {
|
||||||
return new ArrayList<IBaseResource>( myBundle.toListOfResources());
|
return new ArrayList<IBaseResource>(myBundle.toListOfResources());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ public class CustomThymeleafNarrativeGeneratorTest {
|
||||||
public void testGenerator() {
|
public void testGenerator() {
|
||||||
|
|
||||||
CustomThymeleafNarrativeGenerator gen = new CustomThymeleafNarrativeGenerator("classpath:narrative/customnarrative.properties");
|
CustomThymeleafNarrativeGenerator gen = new CustomThymeleafNarrativeGenerator("classpath:narrative/customnarrative.properties");
|
||||||
gen.setFhirContext(ourCtx);
|
|
||||||
|
|
||||||
Practitioner p = new Practitioner();
|
Practitioner p = new Practitioner();
|
||||||
p.addIdentifier("sys", "val1");
|
p.addIdentifier("sys", "val1");
|
||||||
|
@ -28,7 +27,7 @@ public class CustomThymeleafNarrativeGeneratorTest {
|
||||||
p.getName().addFamily("fam1").addGiven("given");
|
p.getName().addFamily("fam1").addGiven("given");
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative(p, narrative);
|
gen.generateNarrative(ourCtx, p, narrative);
|
||||||
|
|
||||||
String actual = narrative.getDiv().getValueAsString();
|
String actual = narrative.getDiv().getValueAsString();
|
||||||
ourLog.info(actual);
|
ourLog.info(actual);
|
||||||
|
|
|
@ -62,14 +62,10 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
value.setBirthDate(new Date(), TemporalPrecisionEnum.DAY);
|
value.setBirthDate(new Date(), TemporalPrecisionEnum.DAY);
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative(value, narrative);
|
gen.generateNarrative(myCtx, value, narrative);
|
||||||
String output = narrative.getDiv().getValueAsString();
|
String output = narrative.getDiv().getValueAsString();
|
||||||
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> joe john <b>BLOW </b></div>"));
|
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> joe john <b>BLOW </b></div>"));
|
||||||
|
|
||||||
String title = gen.generateTitle(value);
|
|
||||||
assertEquals("joe john BLOW (123456)", title);
|
|
||||||
ourLog.info(title);
|
|
||||||
|
|
||||||
// Removed because label is gone in DSTU2
|
// Removed because label is gone in DSTU2
|
||||||
// value.getIdentifierFirstRep().setLabel("FOO MRN 123");
|
// value.getIdentifierFirstRep().setLabel("FOO MRN 123");
|
||||||
// title = gen.generateTitle(value);
|
// title = gen.generateTitle(value);
|
||||||
|
@ -78,6 +74,24 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGeneratePatientWithoutData() throws DataFormatException {
|
||||||
|
Patient value = new Patient();
|
||||||
|
|
||||||
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
|
gen.generateNarrative(myCtx, value, narrative);
|
||||||
|
String output = narrative.getDiv().getValueAsString();
|
||||||
|
assertThat(output, StringContains.containsString("<div>"));
|
||||||
|
|
||||||
|
// Removed because label is gone in DSTU2
|
||||||
|
// value.getIdentifierFirstRep().setLabel("FOO MRN 123");
|
||||||
|
// title = gen.generateTitle(value);
|
||||||
|
// assertEquals("joe john BLOW (FOO MRN 123)", title);
|
||||||
|
// ourLog.info(title);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateEncounter() throws DataFormatException {
|
public void testGenerateEncounter() throws DataFormatException {
|
||||||
Encounter enc = new Encounter();
|
Encounter enc = new Encounter();
|
||||||
|
@ -87,11 +101,6 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
enc.setPeriod(new PeriodDt().setStart(new DateTimeDt("2001-01-02T11:11:00")));
|
enc.setPeriod(new PeriodDt().setStart(new DateTimeDt("2001-01-02T11:11:00")));
|
||||||
enc.setType(EncounterTypeEnum.ANNUAL_DIABETES_MELLITUS_SCREENING);
|
enc.setType(EncounterTypeEnum.ANNUAL_DIABETES_MELLITUS_SCREENING);
|
||||||
|
|
||||||
String title = gen.generateTitle(enc);
|
|
||||||
title = title.replaceAll("00 [A-Z]+ 2001", "00 TZ 2001"); // account for whatever time zone
|
|
||||||
assertEquals("1234567 / ADMS / ambulatory / Tue Jan 02 11:11:00 TZ 2001 - ?", title);
|
|
||||||
ourLog.info(title);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -102,10 +111,6 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
enc.setName("Some Test Org");
|
enc.setName("Some Test Org");
|
||||||
enc.addAddress().addLine("123 Fake St").setCity("Toronto").setState("ON").setCountry("Canada").setZip("12345");
|
enc.addAddress().addLine("123 Fake St").setCity("Toronto").setState("ON").setCountry("Canada").setZip("12345");
|
||||||
|
|
||||||
String title = gen.generateTitle(enc);
|
|
||||||
assertEquals("Some Test Org", title);
|
|
||||||
ourLog.info(title);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -113,7 +118,7 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
Conformance value = myCtx.newXmlParser().parseResource(Conformance.class, new InputStreamReader(getClass().getResourceAsStream("/server-conformance-statement.xml")));
|
Conformance value = myCtx.newXmlParser().parseResource(Conformance.class, new InputStreamReader(getClass().getResourceAsStream("/server-conformance-statement.xml")));
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative(value, narrative);
|
gen.generateNarrative(myCtx, value, narrative);
|
||||||
String output =narrative.getDiv().getValueAsString();
|
String output =narrative.getDiv().getValueAsString();
|
||||||
|
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
|
@ -129,7 +134,7 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
value.addResult().setReference("Observation/3");
|
value.addResult().setReference("Observation/3");
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative("http://hl7.org/fhir/profiles/DiagnosticReport", value, narrative);
|
gen.generateNarrative(myCtx, value, narrative);
|
||||||
String output = narrative.getDiv().getValueAsString();
|
String output = narrative.getDiv().getValueAsString();
|
||||||
|
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
|
@ -158,7 +163,7 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
// assertEquals("Operation Outcome (2 issues)", output);
|
// assertEquals("Operation Outcome (2 issues)", output);
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative(null, oo, narrative);
|
gen.generateNarrative(myCtx, oo, narrative);
|
||||||
String nar = narrative.getDiv().getValueAsString();
|
String nar = narrative.getDiv().getValueAsString();
|
||||||
ourLog.info(nar);
|
ourLog.info(nar);
|
||||||
|
|
||||||
|
@ -201,16 +206,12 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative("http://hl7.org/fhir/profiles/DiagnosticReport", value, narrative);
|
gen.generateNarrative(myCtx, value, narrative);
|
||||||
String output = narrative.getDiv().getValueAsString();
|
String output = narrative.getDiv().getValueAsString();
|
||||||
|
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> Some & Diagnostic Report </div>"));
|
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> Some & Diagnostic Report </div>"));
|
||||||
|
|
||||||
String title = gen.generateTitle(value);
|
|
||||||
// ourLog.info(title);
|
|
||||||
assertEquals("Some & Diagnostic Report - final - 3 observations", title);
|
|
||||||
|
|
||||||
// Now try it with the parser
|
// Now try it with the parser
|
||||||
|
|
||||||
output = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(value);
|
output = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(value);
|
||||||
|
@ -231,13 +232,10 @@ public class DefaultThymeleafNarrativeGeneratorTest {
|
||||||
mp.setDateWritten(new DateTimeDt("2014-09-01"));
|
mp.setDateWritten(new DateTimeDt("2014-09-01"));
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative(mp, narrative);
|
gen.generateNarrative(myCtx, mp, narrative);
|
||||||
assertTrue("Expected medication name of ciprofloaxin within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ciprofloaxin") > -1);
|
assertTrue("Expected medication name of ciprofloaxin within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ciprofloaxin") > -1);
|
||||||
assertTrue("Expected string status of ACTIVE within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ACTIVE") > -1);
|
assertTrue("Expected string status of ACTIVE within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ACTIVE") > -1);
|
||||||
|
|
||||||
String title = gen.generateTitle(mp);
|
|
||||||
assertEquals("ciprofloaxin", title);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.hamcrest.core.IsNot;
|
||||||
import org.hamcrest.core.StringContains;
|
import org.hamcrest.core.StringContains;
|
||||||
import org.hamcrest.text.StringContainsInOrder;
|
import org.hamcrest.text.StringContainsInOrder;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -940,30 +941,15 @@ public class JsonParserTest {
|
||||||
INarrativeGenerator gen = new INarrativeGenerator() {
|
INarrativeGenerator gen = new INarrativeGenerator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateNarrative(IBaseResource theResource, BaseNarrativeDt<?> theNarrative) {
|
public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) {
|
||||||
throw new UnsupportedOperationException();
|
try {
|
||||||
|
theNarrative.setDivAsString("<div>help</div>");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
theNarrative.setStatusAsString("generated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt<?> theNarrative) throws DataFormatException {
|
|
||||||
theNarrative.getDiv().setValueAsString("<div>help</div>");
|
|
||||||
theNarrative.getStatus().setValueAsString("generated");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(String theProfile, IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFhirContext(FhirContext theFhirContext) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FhirContext context = ourCtx;
|
FhirContext context = ourCtx;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.hamcrest.core.IsNot;
|
||||||
import org.hamcrest.core.StringContains;
|
import org.hamcrest.core.StringContains;
|
||||||
import org.hamcrest.text.StringContainsInOrder;
|
import org.hamcrest.text.StringContainsInOrder;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
@ -1246,30 +1247,15 @@ public class XmlParserTest {
|
||||||
INarrativeGenerator gen = new INarrativeGenerator() {
|
INarrativeGenerator gen = new INarrativeGenerator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateNarrative(IBaseResource theResource, BaseNarrativeDt<?> theNarrative) {
|
public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) {
|
||||||
throw new UnsupportedOperationException();
|
try {
|
||||||
|
theNarrative.setDivAsString("<div>help</div>");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
theNarrative.setStatusAsString("generated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt<?> theNarrative) throws DataFormatException {
|
|
||||||
theNarrative.getDiv().setValueAsString("<div>help</div>");
|
|
||||||
theNarrative.getStatus().setValueAsString("generated");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(String theProfile, IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFhirContext(FhirContext theFhirContext) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -298,7 +298,6 @@ public class SearchSearchServerDstu1Test {
|
||||||
|
|
||||||
Patient p = bundle.getResources(Patient.class).get(0);
|
Patient p = bundle.getResources(Patient.class).get(0);
|
||||||
assertEquals("idaaa", p.getNameFirstRep().getFamilyAsSingleString());
|
assertEquals("idaaa", p.getNameFirstRep().getFamilyAsSingleString());
|
||||||
assertEquals("IDAAA (identifier123)", bundle.getEntries().get(0).getTitle().getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -310,7 +309,6 @@ public class SearchSearchServerDstu1Test {
|
||||||
|
|
||||||
Patient p = bundle.getResources(Patient.class).get(0);
|
Patient p = bundle.getResources(Patient.class).get(0);
|
||||||
assertEquals("idaaa", p.getNameFirstRep().getFamilyAsSingleString());
|
assertEquals("idaaa", p.getNameFirstRep().getFamilyAsSingleString());
|
||||||
assertEquals("IDAAA (identifier123)", bundle.getEntries().get(0).getTitle().getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -364,7 +362,6 @@ public class SearchSearchServerDstu1Test {
|
||||||
|
|
||||||
Patient p = bundle.getResources(Patient.class).get(0);
|
Patient p = bundle.getResources(Patient.class).get(0);
|
||||||
assertEquals("idaaa", p.getNameFirstRep().getFamilyAsSingleString());
|
assertEquals("idaaa", p.getNameFirstRep().getFamilyAsSingleString());
|
||||||
assertEquals("IDAAA (identifier123)", bundle.getEntries().get(0).getTitle().getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -129,6 +129,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport {
|
||||||
Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader);
|
Bundle bundle = theContext.newXmlParser().parseResource(Bundle.class, reader);
|
||||||
for (BundleEntryComponent next : bundle.getEntry()) {
|
for (BundleEntryComponent next : bundle.getEntry()) {
|
||||||
ValueSet nextValueSet = (ValueSet) next.getResource();
|
ValueSet nextValueSet = (ValueSet) next.getResource();
|
||||||
|
nextValueSet.getText().setDivAsString("");
|
||||||
String system = nextValueSet.getCodeSystem().getSystem();
|
String system = nextValueSet.getCodeSystem().getSystem();
|
||||||
if (isNotBlank(system)) {
|
if (isNotBlank(system)) {
|
||||||
theCodeSystems.put(system, nextValueSet);
|
theCodeSystems.put(system, nextValueSet);
|
||||||
|
|
|
@ -36,4 +36,17 @@ public abstract class BaseNarrative extends Type implements INarrative {
|
||||||
|
|
||||||
protected abstract XhtmlNode getDiv();
|
protected abstract XhtmlNode getDiv();
|
||||||
|
|
||||||
|
public abstract Enumeration<?> getStatusElement();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public INarrative setStatusAsString(String theString) {
|
||||||
|
getStatusElement().setValueAsString(theString);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStatusAsString() {
|
||||||
|
return getStatusElement().getValueAsString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1527,7 +1527,14 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
|
|
||||||
List<WrapperElement> answers = new ArrayList<InstanceValidator.WrapperElement>();
|
List<WrapperElement> answers = new ArrayList<InstanceValidator.WrapperElement>();
|
||||||
element.getNamedChildren("answer", answers);
|
element.getNamedChildren("answer", answers);
|
||||||
|
switch (qItem.getType()) {
|
||||||
|
case NULL:
|
||||||
|
case GROUP:
|
||||||
|
case DISPLAY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), (answers.size() > 0) || !qItem.getRequired(), "No response answer found for required item "+qItem.getLinkId());
|
rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), (answers.size() > 0) || !qItem.getRequired(), "No response answer found for required item "+qItem.getLinkId());
|
||||||
|
}
|
||||||
if (answers.size() > 1)
|
if (answers.size() > 1)
|
||||||
rule(errors, IssueType.INVALID, answers.get(1).line(), answers.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), "Only one response answer item with this linkId allowed");
|
rule(errors, IssueType.INVALID, answers.get(1).line(), answers.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), "Only one response answer item with this linkId allowed");
|
||||||
|
|
||||||
|
@ -1564,7 +1571,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
validateQuestionnaireResponseItemType(errors, answer, ns, "string");
|
validateQuestionnaireResponseItemType(errors, answer, ns, "string");
|
||||||
break;
|
break;
|
||||||
case TEXT:
|
case TEXT:
|
||||||
validateQuestionnaireResponseItemType(errors, answer, ns, "text");
|
validateQuestionnaireResponseItemType(errors, answer, ns, "string");
|
||||||
break;
|
break;
|
||||||
case URL:
|
case URL:
|
||||||
validateQuestionnaireResponseItemType(errors, answer, ns, "uri");
|
validateQuestionnaireResponseItemType(errors, answer, ns, "uri");
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -38,6 +38,7 @@ import org.hl7.fhir.dstu21.model.Medication;
|
||||||
import org.hl7.fhir.dstu21.model.MedicationOrder;
|
import org.hl7.fhir.dstu21.model.MedicationOrder;
|
||||||
import org.hl7.fhir.dstu21.model.Observation;
|
import org.hl7.fhir.dstu21.model.Observation;
|
||||||
import org.hl7.fhir.dstu21.model.Observation.ObservationStatus;
|
import org.hl7.fhir.dstu21.model.Observation.ObservationStatus;
|
||||||
|
import org.hl7.fhir.dstu21.model.Parameters;
|
||||||
import org.hl7.fhir.dstu21.model.Patient;
|
import org.hl7.fhir.dstu21.model.Patient;
|
||||||
import org.hl7.fhir.dstu21.model.Quantity;
|
import org.hl7.fhir.dstu21.model.Quantity;
|
||||||
import org.hl7.fhir.dstu21.model.QuestionnaireResponse;
|
import org.hl7.fhir.dstu21.model.QuestionnaireResponse;
|
||||||
|
@ -45,11 +46,14 @@ import org.hl7.fhir.dstu21.model.Reference;
|
||||||
import org.hl7.fhir.dstu21.model.StringType;
|
import org.hl7.fhir.dstu21.model.StringType;
|
||||||
import org.hl7.fhir.dstu21.model.UriType;
|
import org.hl7.fhir.dstu21.model.UriType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import net.sf.json.JSON;
|
import net.sf.json.JSON;
|
||||||
import net.sf.json.JSONSerializer;
|
import net.sf.json.JSONSerializer;
|
||||||
|
@ -59,6 +63,39 @@ public class JsonParserDstu21Test {
|
||||||
private static final FhirContext ourCtx = FhirContext.forDstu2_1();
|
private static final FhirContext ourCtx = FhirContext.forDstu2_1();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserDstu21Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserDstu21Test.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeParametersWithId() {
|
||||||
|
Parameters reqParms = new Parameters();
|
||||||
|
IdType patient = new IdType(1);
|
||||||
|
reqParms.addParameter().setName("patient").setValue(patient);
|
||||||
|
|
||||||
|
String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(reqParms);
|
||||||
|
ourLog.info(enc);
|
||||||
|
|
||||||
|
assertThat(enc, containsString("\"valueId\":\"1\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeWithNarrative() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addName().addFamily("Smith").addGiven("John");
|
||||||
|
|
||||||
|
ourCtx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
||||||
|
|
||||||
|
String output = ourCtx.newJsonParser().encodeResourceToString(p);
|
||||||
|
ourLog.info(output);
|
||||||
|
|
||||||
|
assertThat(output, containsString("\"text\":{\"status\":\"generated\",\"div\":\"<div><div class=\\\"hapiHeaderText\\\"> John <b>SMITH </b></div>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void after() {
|
||||||
|
ourCtx.setNarrativeGenerator(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: this should pass
|
// FIXME: this should pass
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.hamcrest.text.StringContainsInOrder;
|
||||||
import org.hl7.fhir.dstu21.model.Address.AddressUse;
|
import org.hl7.fhir.dstu21.model.Address.AddressUse;
|
||||||
import org.hl7.fhir.dstu21.model.AllergyIntolerance;
|
import org.hl7.fhir.dstu21.model.AllergyIntolerance;
|
||||||
import org.hl7.fhir.dstu21.model.Annotation;
|
import org.hl7.fhir.dstu21.model.Annotation;
|
||||||
import org.hl7.fhir.dstu21.model.Attachment;
|
|
||||||
import org.hl7.fhir.dstu21.model.Binary;
|
import org.hl7.fhir.dstu21.model.Binary;
|
||||||
import org.hl7.fhir.dstu21.model.Bundle;
|
import org.hl7.fhir.dstu21.model.Bundle;
|
||||||
import org.hl7.fhir.dstu21.model.Bundle.BundleEntryComponent;
|
import org.hl7.fhir.dstu21.model.Bundle.BundleEntryComponent;
|
||||||
|
@ -77,13 +76,14 @@ import org.hl7.fhir.dstu21.model.StringType;
|
||||||
import org.hl7.fhir.dstu21.model.UriType;
|
import org.hl7.fhir.dstu21.model.UriType;
|
||||||
import org.hl7.fhir.dstu21.model.ValueSet;
|
import org.hl7.fhir.dstu21.model.ValueSet;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||||
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
|
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
|
||||||
import ca.uhn.fhir.rest.client.IGenericClient;
|
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
@ -124,6 +124,24 @@ public class XmlParserDstu21Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeWithNarrative() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addName().addFamily("Smith").addGiven("John");
|
||||||
|
|
||||||
|
ourCtx.setNarrativeGenerator(new DefaultThymeleafNarrativeGenerator());
|
||||||
|
|
||||||
|
String output = ourCtx.newXmlParser().encodeResourceToString(p);
|
||||||
|
ourLog.info(output);
|
||||||
|
|
||||||
|
assertThat(output, containsString("<text><status value=\"generated\"/><div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\"> John <b>SMITH </b>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void after() {
|
||||||
|
ourCtx.setNarrativeGenerator(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeEmptyBinary() {
|
public void testEncodeEmptyBinary() {
|
||||||
String output = ourCtx.newXmlParser().encodeResourceToString(new Binary());
|
String output = ourCtx.newXmlParser().encodeResourceToString(new Binary());
|
||||||
|
@ -541,7 +559,7 @@ public class XmlParserDstu21Test {
|
||||||
mo.addDosageInstruction().getTiming().getRepeat().setBounds(new Duration().setCode("code"));
|
mo.addDosageInstruction().getTiming().getRepeat().setBounds(new Duration().setCode("code"));
|
||||||
String out = ourCtx.newXmlParser().encodeResourceToString(mo);
|
String out = ourCtx.newXmlParser().encodeResourceToString(mo);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
assertThat(out, containsString("</boundsDuration>"));
|
assertThat(out, containsString("</boundsQuantity>"));
|
||||||
|
|
||||||
mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, out);
|
mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, out);
|
||||||
Duration duration = (Duration) mo.getDosageInstruction().get(0).getTiming().getRepeat().getBounds();
|
Duration duration = (Duration) mo.getDosageInstruction().get(0).getTiming().getRepeat().getBounds();
|
||||||
|
@ -551,17 +569,15 @@ public class XmlParserDstu21Test {
|
||||||
/**
|
/**
|
||||||
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
|
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
|
||||||
*/
|
*/
|
||||||
@Test @Ignore
|
@Test
|
||||||
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
|
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
|
||||||
IParser xmlParser = ourCtx.newXmlParser();
|
IParser xmlParser = ourCtx.newXmlParser();
|
||||||
|
|
||||||
String input = IOUtils.toString(XmlParser.class.getResourceAsStream("/medicationstatement_invalidelement.xml"));
|
MedicationStatement ms = new MedicationStatement();
|
||||||
MedicationStatement ms = xmlParser.parseResource(MedicationStatement.class, input);
|
ms.addDosage().setQuantity(new SimpleQuantity().setValue(123));
|
||||||
SimpleQuantity q = (SimpleQuantity) ms.getDosage().get(0).getQuantity();
|
|
||||||
assertEquals("1", q.getValueElement().getValueAsString());
|
|
||||||
|
|
||||||
String output = xmlParser.encodeResourceToString(ms);
|
String output = xmlParser.encodeResourceToString(ms);
|
||||||
assertThat(output, containsString("<quantityQuantity><value value=\"1\"/></quantityQuantity>"));
|
assertThat(output, containsString("<quantityQuantity><value value=\"123\"/></quantityQuantity>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1588,7 +1604,7 @@ public class XmlParserDstu21Test {
|
||||||
/**
|
/**
|
||||||
* See #191
|
* See #191
|
||||||
*/
|
*/
|
||||||
@Test @Ignore
|
@Test
|
||||||
public void testParseBundleWithLinksOfUnknownRelation() throws Exception {
|
public void testParseBundleWithLinksOfUnknownRelation() throws Exception {
|
||||||
String input = IOUtils.toString(XmlParserDstu21Test.class.getResourceAsStream("/bundle_orion.xml"));
|
String input = IOUtils.toString(XmlParserDstu21Test.class.getResourceAsStream("/bundle_orion.xml"));
|
||||||
Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
|
Bundle parsed = ourCtx.newXmlParser().parseResource(Bundle.class, input);
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.startsWith;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
@ -19,6 +21,7 @@ import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
|
import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.dstu21.model.Enumerations.AdministrativeGender;
|
import org.hl7.fhir.dstu21.model.Enumerations.AdministrativeGender;
|
||||||
|
import org.hl7.fhir.dstu21.model.Identifier.IdentifierUse;
|
||||||
import org.hl7.fhir.dstu21.model.Patient;
|
import org.hl7.fhir.dstu21.model.Patient;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
@ -56,10 +59,10 @@ public class ResponseValidatingInterceptorDstu21Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
myInterceptor = new ResponseValidatingInterceptor();
|
myInterceptor = new ResponseValidatingInterceptor();
|
||||||
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
// myInterceptor.setFailOnSeverity(ResultSeverityEnum.ERROR);
|
||||||
// myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
// myInterceptor.setAddResponseHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||||
// myInterceptor.setResponseHeaderName("X-RESP");
|
// myInterceptor.setResponseHeaderName("X-RESP");
|
||||||
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
// myInterceptor.setResponseHeaderValue(RequestValidatingInterceptor.DEFAULT_RESPONSE_HEADER_VALUE);
|
||||||
|
|
||||||
ourServlet.registerInterceptor(myInterceptor);
|
ourServlet.registerInterceptor(myInterceptor);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +94,6 @@ public class ResponseValidatingInterceptorDstu21Test {
|
||||||
assertThat(responseContent, containsString("<severity value=\"error\"/>"));
|
assertThat(responseContent, containsString("<severity value=\"error\"/>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchJsonValidNoValidatorsSpecified() throws Exception {
|
public void testSearchJsonValidNoValidatorsSpecified() throws Exception {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
|
@ -113,7 +115,6 @@ public class ResponseValidatingInterceptorDstu21Test {
|
||||||
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
|
assertThat(status.toString(), not(containsString("X-FHIR-Response-Validation")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchJsonValidNoValidatorsSpecifiedDefaultMessage() throws Exception {
|
public void testSearchJsonValidNoValidatorsSpecifiedDefaultMessage() throws Exception {
|
||||||
myInterceptor.setResponseHeaderValueNoIssues("NO ISSUES");
|
myInterceptor.setResponseHeaderValueNoIssues("NO ISSUES");
|
||||||
|
@ -270,9 +271,54 @@ public class ResponseValidatingInterceptorDstu21Test {
|
||||||
ourLog.trace("Response was:\n{}", responseContent);
|
ourLog.trace("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
assertThat(status.toString(), (containsString("X-FHIR-Response-Validation: {\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"information\",\"code\":\"informational\",\"diagnostics\":\"No issues detected\"}]}")));
|
assertThat(status.toString(), (containsString(
|
||||||
|
"X-FHIR-Response-Validation: {\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"information\",\"code\":\"informational\",\"diagnostics\":\"No issues detected\"}]}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLongHeaderTruncated() throws Exception {
|
||||||
|
IValidatorModule module = new FhirInstanceValidator();
|
||||||
|
myInterceptor.addValidatorModule(module);
|
||||||
|
myInterceptor.setAddResponseOutcomeHeaderOnSeverity(ResultSeverityEnum.INFORMATION);
|
||||||
|
myInterceptor.setFailOnSeverity(null);
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
patient.addContact().setGender(AdministrativeGender.MALE);
|
||||||
|
}
|
||||||
|
patient.setGender(AdministrativeGender.MALE);
|
||||||
|
myReturnResource = patient;
|
||||||
|
|
||||||
|
HttpGet httpPost = new HttpGet("http://localhost:" + ourPort + "/Patient?foo=bar");
|
||||||
|
|
||||||
|
{
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
ourLog.trace("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), endsWith("..."));
|
||||||
|
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), startsWith("{\"resourceType\":\"OperationOutcome\""));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
myInterceptor.setMaximumHeaderLength(100);
|
||||||
|
HttpResponse status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Response was:\n{}", status);
|
||||||
|
ourLog.trace("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), endsWith("..."));
|
||||||
|
assertThat(status.getFirstHeader("X-FHIR-Response-Validation").getValue(), startsWith("{\"resourceType\":\"OperationOutcome\""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void afterClass() throws Exception {
|
public static void afterClass() throws Exception {
|
||||||
|
@ -309,7 +355,7 @@ public class ResponseValidatingInterceptorDstu21Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Search
|
@Search
|
||||||
public ArrayList<IBaseResource> search(@OptionalParam(name="foo") StringParam theString) {
|
public ArrayList<IBaseResource> search(@OptionalParam(name = "foo") StringParam theString) {
|
||||||
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
|
||||||
myReturnResource.setId("1");
|
myReturnResource.setId("1");
|
||||||
retVal.add(myReturnResource);
|
retVal.add(myReturnResource);
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.hl7.fhir.dstu21.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TestRule;
|
import org.junit.rules.TestRule;
|
||||||
|
@ -170,7 +171,7 @@ public class FhirInstanceValidatorDstu21Test {
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (SingleValidationMessage next : theOutput.getMessages()) {
|
for (SingleValidationMessage next : theOutput.getMessages()) {
|
||||||
ourLog.info("Result {}: {} - {} - {}", new Object[] { index, next.getSeverity(), next.getLocationString(), next.getMessage() });
|
ourLog.info("Result {}: {} - {}:{} {} - {}", new Object[] { index, next.getSeverity(), defaultString(next.getLocationLine()), defaultString(next.getLocationCol()), next.getLocationString(), next.getMessage() });
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
retVal.add(next);
|
retVal.add(next);
|
||||||
|
@ -179,6 +180,10 @@ public class FhirInstanceValidatorDstu21Test {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object defaultString(Integer theLocationLine) {
|
||||||
|
return theLocationLine != null ? theLocationLine.toString() : "";
|
||||||
|
}
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public TestRule watcher = new TestWatcher() {
|
public TestRule watcher = new TestWatcher() {
|
||||||
protected void starting(Description description) {
|
protected void starting(Description description) {
|
||||||
|
@ -262,7 +267,22 @@ public class FhirInstanceValidatorDstu21Test {
|
||||||
String input = IOUtils.toString(FhirInstanceValidatorDstu21Test.class.getResourceAsStream("/qr_jon.xml"));
|
String input = IOUtils.toString(FhirInstanceValidatorDstu21Test.class.getResourceAsStream("/qr_jon.xml"));
|
||||||
|
|
||||||
ValidationResult output = myVal.validateWithResult(input);
|
ValidationResult output = myVal.validateWithResult(input);
|
||||||
assertEquals(output.toString(), 12, output.getMessages().size());
|
logResultsAndReturnAll(output);
|
||||||
|
|
||||||
|
assertEquals(output.toString(), 3, output.getMessages().size());
|
||||||
|
ourLog.info(output.getMessages().get(0).getLocationString());
|
||||||
|
ourLog.info(output.getMessages().get(0).getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testValidateStructureDefinition() throws IOException {
|
||||||
|
String input = IOUtils.toString(FhirInstanceValidatorDstu21Test.class.getResourceAsStream("/sdc-questionnaire.profile.xml"));
|
||||||
|
|
||||||
|
ValidationResult output = myVal.validateWithResult(input);
|
||||||
|
logResultsAndReturnAll(output);
|
||||||
|
|
||||||
|
assertEquals(output.toString(), 3, output.getMessages().size());
|
||||||
ourLog.info(output.getMessages().get(0).getLocationString());
|
ourLog.info(output.getMessages().get(0).getLocationString());
|
||||||
ourLog.info(output.getMessages().get(0).getMessage());
|
ourLog.info(output.getMessages().get(0).getMessage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
<Bundle
|
||||||
|
xmlns="http://hl7.org/fhir">
|
||||||
|
<id value="487d3669-0e1c-4867-b124-400d1849548d"></id>
|
||||||
|
<type value="searchset"></type>
|
||||||
|
<base value="http://localhost:19080/fhir/dstu1"></base>
|
||||||
|
<link>
|
||||||
|
<relation value="just trying add link"></relation>
|
||||||
|
<url value="blarion"></url>
|
||||||
|
</link>
|
||||||
|
<link>
|
||||||
|
<relation value="self"></relation>
|
||||||
|
<url value="http://localhost:19080/fhir/dstu1/Observation?subject.identifier=puppet|CLONE-AA102"></url>
|
||||||
|
</link>
|
||||||
|
<entry>
|
||||||
|
<link>
|
||||||
|
<relation value="orionhealth.edit"></relation>
|
||||||
|
<url value="Observation"></url>
|
||||||
|
</link>
|
||||||
|
<resource>
|
||||||
|
<Observation
|
||||||
|
xmlns="http://hl7.org/fhir">
|
||||||
|
<id value="0d87f02c-da2c-4551-9ead-2956f0165a4f"></id>
|
||||||
|
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
||||||
|
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
||||||
|
<extension url="http://orionhealth.com/fhir/extensions#received-instant">
|
||||||
|
<valueInstant value="2015-06-25T17:08:47.190+12:00"></valueInstant>
|
||||||
|
</extension>
|
||||||
|
<code>
|
||||||
|
<coding>
|
||||||
|
<system value="http://loinc.org"></system>
|
||||||
|
<code value="8867-4"></code>
|
||||||
|
</coding>
|
||||||
|
</code>
|
||||||
|
<valueString value="observationValue"></valueString>
|
||||||
|
<status value="final"></status>
|
||||||
|
<reliability value="ok"></reliability>
|
||||||
|
<subject>
|
||||||
|
<reference value="Patient/INGE6TSFFVAUCMJQGJAHA5LQOBSXI"></reference>
|
||||||
|
</subject>
|
||||||
|
</Observation>
|
||||||
|
</resource>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<link>
|
||||||
|
<relation value="orionhealth.edit"></relation>
|
||||||
|
<url value="Observation"></url>
|
||||||
|
</link>
|
||||||
|
<resource>
|
||||||
|
<Observation
|
||||||
|
xmlns="http://hl7.org/fhir">
|
||||||
|
<id value="c54ac0cc-a99f-40aa-9541-c5aa853a2e88"></id>
|
||||||
|
<extension url="http://orionhealth.com/fhir/extensions#created-by"></extension>
|
||||||
|
<extension url="http://orionhealth.com/fhir/extensions#last-modified-by"></extension>
|
||||||
|
<extension url="http://orionhealth.com/fhir/extensions#received-instant">
|
||||||
|
<valueInstant value="2015-06-25T17:08:47.190+12:00"></valueInstant>
|
||||||
|
</extension>
|
||||||
|
<code>
|
||||||
|
<coding>
|
||||||
|
<system value="http://loinc.org"></system>
|
||||||
|
<code value="3141-9"></code>
|
||||||
|
</coding>
|
||||||
|
</code>
|
||||||
|
<valueString value="observationValue"></valueString>
|
||||||
|
<status value="final"></status>
|
||||||
|
<reliability value="ok"></reliability>
|
||||||
|
<subject>
|
||||||
|
<reference value="Patient/INGE6TSFFVAUCMJQGJAHA5LQOBSXI"></reference>
|
||||||
|
</subject>
|
||||||
|
</Observation>
|
||||||
|
</resource>
|
||||||
|
</entry>
|
||||||
|
</Bundle>
|
File diff suppressed because it is too large
Load Diff
|
@ -29,7 +29,6 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
@ -94,16 +93,6 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myContext.getNarrativeGenerator() != null) {
|
|
||||||
String title = myContext.getNarrativeGenerator().generateTitle(next);
|
|
||||||
ourLog.trace("Narrative generator created title: {}", title);
|
|
||||||
if (StringUtils.isNotBlank(title)) {
|
|
||||||
ResourceMetadataKeyEnum.TITLE.put(next, title);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ourLog.trace("No narrative generator specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<BaseResourceReferenceDt> references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
|
List<BaseResourceReferenceDt> references = myContext.newTerser().getAllPopulatedChildElementsOfType(next, BaseResourceReferenceDt.class);
|
||||||
do {
|
do {
|
||||||
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
|
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
|
||||||
|
@ -190,16 +179,6 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myContext.getNarrativeGenerator() != null) {
|
|
||||||
String title = myContext.getNarrativeGenerator().generateTitle(next);
|
|
||||||
ourLog.trace("Narrative generator created title: {}", title);
|
|
||||||
if (StringUtils.isNotBlank(title)) {
|
|
||||||
ResourceMetadataKeyEnum.TITLE.put(next, title);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ourLog.trace("No narrative generator specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ResourceReferenceInfo> references = myContext.newTerser().getAllResourceReferences(next);
|
List<ResourceReferenceInfo> references = myContext.newTerser().getAllResourceReferences(next);
|
||||||
do {
|
do {
|
||||||
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
|
List<IResource> addedResourcesThisPass = new ArrayList<IResource>();
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class CustomThymeleafNarrativeGeneratorDstu2Test {
|
||||||
p.getName().addFamily("fam1").addGiven("given");
|
p.getName().addFamily("fam1").addGiven("given");
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
gen.generateNarrative(p, narrative);
|
gen.generateNarrative(ourCtx, p, narrative);
|
||||||
|
|
||||||
String actual = narrative.getDiv().getValueAsString();
|
String actual = narrative.getDiv().getValueAsString();
|
||||||
ourLog.info(actual);
|
ourLog.info(actual);
|
||||||
|
|
|
@ -62,23 +62,15 @@ public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
|
||||||
value.setBirthDate(new Date(), TemporalPrecisionEnum.DAY);
|
value.setBirthDate(new Date(), TemporalPrecisionEnum.DAY);
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
myGen.generateNarrative(value, narrative);
|
myGen.generateNarrative(ourCtx, value, narrative);
|
||||||
String output = narrative.getDiv().getValueAsString();
|
String output = narrative.getDiv().getValueAsString();
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> joe john <b>BLOW </b></div>"));
|
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> joe john <b>BLOW </b></div>"));
|
||||||
|
|
||||||
String title = myGen.generateTitle(value);
|
|
||||||
assertEquals("joe john BLOW (123456)", title);
|
|
||||||
// ourLog.info(title);
|
|
||||||
|
|
||||||
value.getIdentifierFirstRep().setValue("FOO MRN 123");
|
|
||||||
title = myGen.generateTitle(value);
|
|
||||||
assertEquals("joe john BLOW (FOO MRN 123)", title);
|
|
||||||
// ourLog.info(title);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore
|
||||||
public void testGenerateEncounter() throws DataFormatException {
|
public void testGenerateEncounter() throws DataFormatException {
|
||||||
Encounter enc = new Encounter();
|
Encounter enc = new Encounter();
|
||||||
|
|
||||||
|
@ -87,30 +79,13 @@ public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
|
||||||
enc.setPeriod(new PeriodDt().setStart(new DateTimeDt("2001-01-02T11:11:00")));
|
enc.setPeriod(new PeriodDt().setStart(new DateTimeDt("2001-01-02T11:11:00")));
|
||||||
enc.setType(ca.uhn.fhir.model.dstu2.valueset.EncounterTypeEnum.ANNUAL_DIABETES_MELLITUS_SCREENING);
|
enc.setType(ca.uhn.fhir.model.dstu2.valueset.EncounterTypeEnum.ANNUAL_DIABETES_MELLITUS_SCREENING);
|
||||||
|
|
||||||
String title = myGen.generateTitle(enc);
|
|
||||||
title = title.replaceAll("00 [A-Z0-9:+-]+ 2001", "00 TZ 2001"); // account for whatever time zone
|
|
||||||
assertEquals("1234567 / ADMS / ambulatory / Tue Jan 02 11:11:00 TZ 2001 - ?", title);
|
|
||||||
ourLog.info(title);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGenerateDiagnosticReport() throws DataFormatException {
|
|
||||||
DiagnosticReport value = new DiagnosticReport();
|
|
||||||
value.getCode().setText("Some Diagnostic Report");
|
|
||||||
|
|
||||||
value.addResult().setReference("Observation/1");
|
|
||||||
value.addResult().setReference("Observation/2");
|
|
||||||
value.addResult().setReference("Observation/3");
|
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
myGen.generateNarrative("http://hl7.org/fhir/profiles/DiagnosticReport", value, narrative);
|
myGen.generateNarrative(ourCtx, enc, narrative);
|
||||||
String output = narrative.getDiv().getValueAsString();
|
|
||||||
|
|
||||||
ourLog.info(output);
|
assertEquals("", narrative.getDivAsString());
|
||||||
assertThat(output, StringContains.containsString(value.getCode().getTextElement().getValue()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateOperationOutcome() {
|
public void testGenerateOperationOutcome() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
@ -133,17 +108,12 @@ public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
|
||||||
// assertEquals("Operation Outcome (2 issues)", output);
|
// assertEquals("Operation Outcome (2 issues)", output);
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
myGen.generateNarrative(null, oo, narrative);
|
myGen.generateNarrative(ourCtx, oo, narrative);
|
||||||
String output = narrative.getDiv().getValueAsString();
|
String output = narrative.getDiv().getValueAsString();
|
||||||
|
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
|
|
||||||
// oo = new OperationOutcome();
|
assertThat(output, containsString("<td><pre>YThis is a warning</pre></td>"));
|
||||||
// oo.addIssue().setSeverity(IssueSeverityEnum.FATAL).setDetails("AA");
|
|
||||||
// output = gen.generateTitle(oo);
|
|
||||||
// ourLog.info(output);
|
|
||||||
// assertEquals("Operation Outcome (fatal)", output);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -177,22 +147,17 @@ public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
myGen.generateNarrative("http://hl7.org/fhir/profiles/DiagnosticReport", value, narrative);
|
myGen.generateNarrative(ourCtx, value, narrative);
|
||||||
String output = narrative.getDiv().getValueAsString();
|
String output = narrative.getDiv().getValueAsString();
|
||||||
|
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> Some & Diagnostic Report </div>"));
|
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> Some & Diagnostic Report </div>"));
|
||||||
|
|
||||||
String title = myGen.generateTitle(value);
|
|
||||||
// ourLog.info(title);
|
|
||||||
assertEquals("Some & Diagnostic Report - final - 3 observations", title);
|
|
||||||
|
|
||||||
// Now try it with the parser
|
// Now try it with the parser
|
||||||
|
|
||||||
output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(value);
|
output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(value);
|
||||||
ourLog.info(output);
|
ourLog.info(output);
|
||||||
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> Some & Diagnostic Report </div>"));
|
assertThat(output, StringContains.containsString("<div class=\"hapiHeaderText\"> Some & Diagnostic Report </div>"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -208,14 +173,11 @@ public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
|
||||||
mp.setDateWritten(new DateTimeDt("2014-09-01"));
|
mp.setDateWritten(new DateTimeDt("2014-09-01"));
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
myGen.generateNarrative(mp, narrative);
|
myGen.generateNarrative(ourCtx, mp, narrative);
|
||||||
|
|
||||||
assertTrue("Expected medication name of ciprofloaxin within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ciprofloaxin") > -1);
|
assertTrue("Expected medication name of ciprofloaxin within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ciprofloaxin") > -1);
|
||||||
assertTrue("Expected string status of ACTIVE within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ACTIVE") > -1);
|
assertTrue("Expected string status of ACTIVE within narrative: " + narrative.getDiv().toString(), narrative.getDiv().toString().indexOf("ACTIVE") > -1);
|
||||||
|
|
||||||
String title = myGen.generateTitle(mp);
|
|
||||||
assertEquals("ciprofloaxin", title);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -224,14 +186,11 @@ public class DefaultThymeleafNarrativeGeneratorTestDstu2 {
|
||||||
med.getCode().setText("ciproflaxin");
|
med.getCode().setText("ciproflaxin");
|
||||||
|
|
||||||
NarrativeDt narrative = new NarrativeDt();
|
NarrativeDt narrative = new NarrativeDt();
|
||||||
myGen.generateNarrative(med, narrative);
|
myGen.generateNarrative(ourCtx, med, narrative);
|
||||||
|
|
||||||
String string = narrative.getDiv().toString();
|
String string = narrative.getDiv().toString();
|
||||||
assertThat(string, containsString("ciproflaxin"));
|
assertThat(string, containsString("ciproflaxin"));
|
||||||
|
|
||||||
String title = myGen.generateTitle(med);
|
|
||||||
assertEquals("ciproflaxin", title);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,18 +110,17 @@ public class XmlParserDstu2Test {
|
||||||
assertEquals(1, parsed.getUndeclaredExtensions().size());
|
assertEquals(1, parsed.getUndeclaredExtensions().size());
|
||||||
ExtensionDt ext = parsed.getUndeclaredExtensions().get(0);
|
ExtensionDt ext = parsed.getUndeclaredExtensions().get(0);
|
||||||
assertEquals("http://example.com", ext.getUrl());
|
assertEquals("http://example.com", ext.getUrl());
|
||||||
assertEquals("THIS IS MARKDOWN", ((MarkdownDt)ext.getValue()).getValue());
|
assertEquals("THIS IS MARKDOWN", ((MarkdownDt) ext.getValue()).getValue());
|
||||||
|
|
||||||
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||||
assertThat(encoded, containsString("<valueMarkdown value=\"THIS IS MARKDOWN\"/>"));
|
assertThat(encoded, containsString("<valueMarkdown value=\"THIS IS MARKDOWN\"/>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChoiceTypeWithProfiledType2() {
|
public void testChoiceTypeWithProfiledType2() {
|
||||||
Parameters par = new Parameters();
|
Parameters par = new Parameters();
|
||||||
par.addParameter().setValue((StringDt)new StringDt().setValue("ST"));
|
par.addParameter().setValue((StringDt) new StringDt().setValue("ST"));
|
||||||
par.addParameter().setValue((MarkdownDt)new MarkdownDt().setValue("MD"));
|
par.addParameter().setValue((MarkdownDt) new MarkdownDt().setValue("MD"));
|
||||||
|
|
||||||
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(par);
|
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(par);
|
||||||
ourLog.info(str);
|
ourLog.info(str);
|
||||||
|
@ -134,8 +133,6 @@ public class XmlParserDstu2Test {
|
||||||
assertEquals(MarkdownDt.class, par.getParameter().get(1).getValue().getClass());
|
assertEquals(MarkdownDt.class, par.getParameter().get(1).getValue().getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBundleWithBinary() {
|
public void testBundleWithBinary() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
@ -184,7 +181,6 @@ public class XmlParserDstu2Test {
|
||||||
ourCtx.newJsonParser().parseResource(encoded);
|
ourCtx.newJsonParser().parseResource(encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeDoesntIncludeUuidId() {
|
public void testEncodeDoesntIncludeUuidId() {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -195,7 +191,6 @@ public class XmlParserDstu2Test {
|
||||||
assertThat(actual, not(containsString("78ef6f64c2f2")));
|
assertThat(actual, not(containsString("78ef6f64c2f2")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContainedResourceInExtensionUndeclared() {
|
public void testContainedResourceInExtensionUndeclared() {
|
||||||
Patient p = new Patient();
|
Patient p = new Patient();
|
||||||
|
@ -340,7 +335,6 @@ public class XmlParserDstu2Test {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAndParseExtensions() throws Exception {
|
public void testEncodeAndParseExtensions() throws Exception {
|
||||||
|
|
||||||
|
@ -566,7 +560,7 @@ public class XmlParserDstu2Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for #233 - This was reversed after a conversation with Grahame
|
* Test for #233
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAndParseProfiledDatatype() {
|
public void testEncodeAndParseProfiledDatatype() {
|
||||||
|
@ -574,7 +568,7 @@ public class XmlParserDstu2Test {
|
||||||
mo.addDosageInstruction().getTiming().getRepeat().setBounds(new DurationDt().setCode("code"));
|
mo.addDosageInstruction().getTiming().getRepeat().setBounds(new DurationDt().setCode("code"));
|
||||||
String out = ourCtx.newXmlParser().encodeResourceToString(mo);
|
String out = ourCtx.newXmlParser().encodeResourceToString(mo);
|
||||||
ourLog.info(out);
|
ourLog.info(out);
|
||||||
assertThat(out, containsString("</boundsDuration>"));
|
assertThat(out, containsString("</boundsQuantity>"));
|
||||||
|
|
||||||
mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, out);
|
mo = ourCtx.newXmlParser().parseResource(MedicationOrder.class, out);
|
||||||
DurationDt duration = (DurationDt) mo.getDosageInstruction().get(0).getTiming().getRepeat().getBounds();
|
DurationDt duration = (DurationDt) mo.getDosageInstruction().get(0).getTiming().getRepeat().getBounds();
|
||||||
|
@ -587,7 +581,6 @@ public class XmlParserDstu2Test {
|
||||||
* Disabled because we reverted this change after a conversation with Grahame
|
* Disabled because we reverted this change after a conversation with Grahame
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
|
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
|
||||||
IParser xmlParser = ourCtx.newXmlParser();
|
IParser xmlParser = ourCtx.newXmlParser();
|
||||||
|
|
||||||
|
@ -597,7 +590,7 @@ public class XmlParserDstu2Test {
|
||||||
assertEquals("1", q.getValueElement().getValueAsString());
|
assertEquals("1", q.getValueElement().getValueAsString());
|
||||||
|
|
||||||
String output = xmlParser.encodeResourceToString(ms);
|
String output = xmlParser.encodeResourceToString(ms);
|
||||||
assertThat(output, containsString("<quantitySimpleQuantity><value value=\"1\"/></quantitySimpleQuantity>"));
|
assertThat(output, containsString("<quantityQuantity><value value=\"1\"/></quantityQuantity>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -54,7 +54,6 @@ import ca.uhn.fhir.rest.annotation.Read;
|
||||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
import ca.uhn.fhir.rest.api.RequestTypeEnum;
|
||||||
import ca.uhn.fhir.rest.method.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
import ca.uhn.fhir.rest.server.BundleInclusionRule;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
@ -89,6 +88,22 @@ public class ResponseHighlightingInterceptorTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetInvalidResourceNoAcceptHeader() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Foobar/123");
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
|
||||||
|
ourLog.info("Resp: {}", responseContent);
|
||||||
|
assertEquals(400, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertThat(responseContent, not(stringContainsInOrder("<span class='hlTagName'>OperationOutcome</span>", "Unknown resource type 'Foobar' - Server knows how to handle")));
|
||||||
|
assertThat(responseContent, (stringContainsInOrder("Unknown resource type 'Foobar'")));
|
||||||
|
assertThat(status.getFirstHeader("Content-Type").getValue(), containsString("application/xml+fhir"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetRoot() throws Exception {
|
public void testGetRoot() throws Exception {
|
||||||
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/");
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/");
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
package org.hl7.fhir.instance.model;
|
package org.hl7.fhir.instance.model;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.instance.model.Narrative.NarrativeStatus;
|
||||||
import org.hl7.fhir.instance.model.api.INarrative;
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
|
||||||
public abstract class BaseNarrative extends Type implements INarrative {
|
public abstract class BaseNarrative extends Type implements INarrative {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public INarrative setStatusAsString(String theString) {
|
||||||
|
getStatusElement().setValueAsString(theString);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStatusAsString() {
|
||||||
|
return getStatusElement().getValueAsString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of
|
* Sets the value of
|
||||||
*
|
*
|
||||||
|
@ -36,4 +48,6 @@ public abstract class BaseNarrative extends Type implements INarrative {
|
||||||
|
|
||||||
protected abstract XhtmlNode getDiv();
|
protected abstract XhtmlNode getDiv();
|
||||||
|
|
||||||
|
public abstract Enumeration<?> getStatusElement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.hl7.fhir.instance.model.ValueSet;
|
||||||
import org.hl7.fhir.instance.model.ValueSet.ConceptDefinitionComponent;
|
import org.hl7.fhir.instance.model.ValueSet.ConceptDefinitionComponent;
|
||||||
import org.hl7.fhir.instance.model.ValueSet.ValueSetCodeSystemComponent;
|
import org.hl7.fhir.instance.model.ValueSet.ValueSetCodeSystemComponent;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
@ -975,30 +976,15 @@ public class JsonParserHl7OrgTest {
|
||||||
INarrativeGenerator gen = new INarrativeGenerator() {
|
INarrativeGenerator gen = new INarrativeGenerator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateNarrative(IBaseResource theResource, BaseNarrativeDt<?> theNarrative) {
|
public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) {
|
||||||
throw new UnsupportedOperationException();
|
try {
|
||||||
|
theNarrative.setDivAsString("<div>help</div>");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
theNarrative.setStatusAsString("generated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt<?> theNarrative) throws DataFormatException {
|
|
||||||
theNarrative.getDiv().setValueAsString("<div>help</div>");
|
|
||||||
theNarrative.getStatus().setValueAsString("generated");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(String theProfile, IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFhirContext(FhirContext theFhirContext) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FhirContext context = ourCtx;
|
FhirContext context = ourCtx;
|
||||||
|
|
|
@ -58,6 +58,7 @@ import org.hl7.fhir.instance.model.SimpleQuantity;
|
||||||
import org.hl7.fhir.instance.model.Specimen;
|
import org.hl7.fhir.instance.model.Specimen;
|
||||||
import org.hl7.fhir.instance.model.StringType;
|
import org.hl7.fhir.instance.model.StringType;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.INarrative;
|
||||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
|
@ -1385,30 +1386,15 @@ public class XmlParserHl7OrgDstu2Test {
|
||||||
INarrativeGenerator gen = new INarrativeGenerator() {
|
INarrativeGenerator gen = new INarrativeGenerator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateNarrative(IBaseResource theResource, BaseNarrativeDt<?> theNarrative) {
|
public void generateNarrative(FhirContext theContext, IBaseResource theResource, INarrative theNarrative) {
|
||||||
throw new UnsupportedOperationException();
|
try {
|
||||||
|
theNarrative.setDivAsString("<div>help</div>");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
theNarrative.setStatusAsString("generated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void generateNarrative(String theProfile, IBaseResource theResource, BaseNarrativeDt<?> theNarrative) throws DataFormatException {
|
|
||||||
theNarrative.getDiv().setValueAsString("<div>help</div>");
|
|
||||||
theNarrative.getStatus().setValueAsString("generated");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateTitle(String theProfile, IBaseResource theResource) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFhirContext(FhirContext theFhirContext) {
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FhirContext context = ourCtx;
|
FhirContext context = ourCtx;
|
||||||
|
|
|
@ -600,21 +600,6 @@ public class BaseController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* DSTU2 no longer has a title in the bundle format, but it's still useful here..
|
|
||||||
*/
|
|
||||||
if (bundle != null) {
|
|
||||||
INarrativeGenerator gen = context.getNarrativeGenerator();
|
|
||||||
if (gen != null) {
|
|
||||||
for (BundleEntry next : bundle.getEntries()) {
|
|
||||||
if (next.getTitle().isEmpty() && next.getResource() != null) {
|
|
||||||
String title = gen.generateTitle(next.getResource());
|
|
||||||
next.getTitle().setValue(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resultDescription.append(" (").append(resultBody.length() + " bytes)");
|
resultDescription.append(" (").append(resultBody.length() + " bytes)");
|
||||||
|
|
||||||
Header[] requestHeaders = lastRequest != null ? applyHeaderFilters(lastRequest.getAllHeaders()) : new Header[0];
|
Header[] requestHeaders = lastRequest != null ? applyHeaderFilters(lastRequest.getAllHeaders()) : new Header[0];
|
||||||
|
|
8
pom.xml
8
pom.xml
|
@ -335,8 +335,8 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.transaction</groupId>
|
<groupId>javax.transaction</groupId>
|
||||||
<artifactId>jta</artifactId>
|
<artifactId>javax.transaction-api</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.validation</groupId>
|
<groupId>javax.validation</groupId>
|
||||||
|
@ -556,7 +556,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate</groupId>
|
<groupId>org.hibernate</groupId>
|
||||||
<artifactId>hibernate-search-orm</artifactId>
|
<artifactId>hibernate-search-orm</artifactId>
|
||||||
<version>5.5.1.Final</version>
|
<version>5.5.2.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.javassist</groupId>
|
<groupId>org.javassist</groupId>
|
||||||
|
@ -941,7 +941,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.puppycrawl.tools</groupId>
|
<groupId>com.puppycrawl.tools</groupId>
|
||||||
<artifactId>checkstyle</artifactId>
|
<artifactId>checkstyle</artifactId>
|
||||||
<version>6.13</version>
|
<version>6.14.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
|
|
@ -122,6 +122,23 @@
|
||||||
Add DSTU2.1 example to hpia-fhir-jpaserver-example. Thanks to Karl
|
Add DSTU2.1 example to hpia-fhir-jpaserver-example. Thanks to Karl
|
||||||
Davis for the Pull Request!
|
Davis for the Pull Request!
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
RestfulServer#setUseBrowserFriendlyContentTypes has been deprecated and its
|
||||||
|
functionality removed. The intention of this feature was that if it
|
||||||
|
detected a request coming in from a browser, it would serve up JSON/XML
|
||||||
|
using content types that caused the browsers to pretty print. But
|
||||||
|
each browser has different rules for when to pretty print, and
|
||||||
|
after we wrote that feature both Chrome and FF changed their rules to break it anyhow.
|
||||||
|
ResponseHighlightingInterceptor provides a better implementation of
|
||||||
|
this functionality and should be used instead.
|
||||||
|
</action>
|
||||||
|
<action type="remove">
|
||||||
|
Narrative generator framework has removed the
|
||||||
|
ability to generate resource titles. This
|
||||||
|
functionality was only useful for DSTU1
|
||||||
|
implementations and wasn't compatible
|
||||||
|
with coming changes to that API.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="1.3" date="2015-11-14">
|
<release version="1.3" date="2015-11-14">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue