Fix #24 - Add a bunch of elements to the automatically generated
conformance profiles to ensure that they validate against the HL7 schemas.
This commit is contained in:
parent
7192c9348a
commit
c214f7fe19
|
@ -184,7 +184,9 @@ public class GenericClientExample {
|
|||
Patient patient = client.read(Patient.class, id); // search for patient 123 on example.com
|
||||
// END SNIPPET: readabsolute
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<release version="0.7" date="TBD">
|
||||
<action type="add" dev="suranga">
|
||||
Documentation fixes
|
||||
</action>
|
||||
</action>
|
||||
<action type="add" dev="dougmartin">
|
||||
Add a collection of new methods on the generic client which support the
|
||||
<![CDATA[
|
||||
|
@ -45,6 +45,11 @@
|
|||
Summary (in the bundle entry) is now encoded by the XML and JSON parsers if supplied. Thanks to David Hay of
|
||||
Orion Health for reporting this!
|
||||
</action>
|
||||
<action type="fix" issue="24">
|
||||
Conformance profiles which are automatically generated by the server were missing a few mandatory elements,
|
||||
which meant that the profile did not correctly validate. Thanks to Bill de Beaubien of Systems Made Simple
|
||||
for reporting this!
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.6" date="2014-Sep-08" description="This release brings a number of new features and bug fixes!">
|
||||
<!--
|
||||
|
|
|
@ -91,4 +91,11 @@ public class DateTimeDt extends BaseDateTimeDt {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of DateTimeDt with the current system time and SECOND precision
|
||||
*/
|
||||
public static DateTimeDt withCurrentTime() {
|
||||
return new DateTimeDt(new Date(), TemporalPrecisionEnum.SECOND);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -153,11 +153,11 @@ public class InstantDt extends BaseDateTimeDt {
|
|||
}
|
||||
|
||||
/**
|
||||
* Factory method which creates a new InstantDt and initializes it with the
|
||||
* Factory method which creates a new InstantDt with millisecond precision and initializes it with the
|
||||
* current time.
|
||||
*/
|
||||
public static InstantDt withCurrentTime() {
|
||||
return new InstantDt(new Date());
|
||||
return new InstantDt(new Date(), TemporalPrecisionEnum.MILLI);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
|
|||
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.annotation.Metadata;
|
||||
|
@ -70,14 +71,24 @@ import ca.uhn.fhir.util.ExtensionConstants;
|
|||
*/
|
||||
public class ServerConformanceProvider {
|
||||
|
||||
private volatile Conformance myConformance;
|
||||
private final RestfulServer myRestfulServer;
|
||||
private boolean myCache = true;
|
||||
private volatile Conformance myConformance;
|
||||
private String myPublisher = "Not provided";
|
||||
private final RestfulServer myRestfulServer;
|
||||
|
||||
public ServerConformanceProvider(RestfulServer theRestfulServer) {
|
||||
myRestfulServer = theRestfulServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the "publisher" that will be placed in the generated conformance statement. As this
|
||||
* is a mandatory element, the value should not be null (although this is not enforced). The value defaults
|
||||
* to "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
*/
|
||||
public String getPublisher() {
|
||||
return myPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually create and return the conformance statement
|
||||
*
|
||||
|
@ -91,6 +102,11 @@ public class ServerConformanceProvider {
|
|||
|
||||
Conformance retVal = new Conformance();
|
||||
|
||||
retVal.setPublisher(myPublisher);
|
||||
retVal.setDate(DateTimeDt.withCurrentTime());
|
||||
retVal.setFhirVersion("0.80"); // TODO: pull from model
|
||||
retVal.setAcceptUnknown(false); // TODO: make this configurable - this is a fairly big effort since the parser needs to be modified to actually allow it
|
||||
|
||||
retVal.getImplementation().setDescription(myRestfulServer.getImplementationDescription());
|
||||
retVal.getSoftware().setName(myRestfulServer.getServerName());
|
||||
retVal.getSoftware().setVersion(myRestfulServer.getServerVersion());
|
||||
|
@ -177,6 +193,51 @@ public class ServerConformanceProvider {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private void handleDynamicSearchMethodBinding(RestResource resource, RuntimeResourceDefinition def, TreeSet<String> includes, DynamicSearchMethodBinding searchMethodBinding) {
|
||||
includes.addAll(searchMethodBinding.getIncludes());
|
||||
|
||||
List<RuntimeSearchParam> searchParameters = new ArrayList<RuntimeSearchParam>();
|
||||
searchParameters.addAll(searchMethodBinding.getSearchParams());
|
||||
sortRuntimeSearchParameters(searchParameters);
|
||||
|
||||
if (!searchParameters.isEmpty()) {
|
||||
|
||||
for (RuntimeSearchParam nextParameter : searchParameters) {
|
||||
|
||||
String nextParamName = nextParameter.getName();
|
||||
|
||||
// String chain = null;
|
||||
String nextParamUnchainedName = nextParamName;
|
||||
if (nextParamName.contains(".")) {
|
||||
// chain = nextParamName.substring(nextParamName.indexOf('.') + 1);
|
||||
nextParamUnchainedName = nextParamName.substring(0, nextParamName.indexOf('.'));
|
||||
}
|
||||
|
||||
String nextParamDescription = nextParameter.getDescription();
|
||||
|
||||
/*
|
||||
* If the parameter has no description, default to the one from the resource
|
||||
*/
|
||||
if (StringUtils.isBlank(nextParamDescription)) {
|
||||
RuntimeSearchParam paramDef = def.getSearchParam(nextParamUnchainedName);
|
||||
if (paramDef != null) {
|
||||
nextParamDescription = paramDef.getDescription();
|
||||
}
|
||||
}
|
||||
|
||||
RestResourceSearchParam param;
|
||||
param = resource.addSearchParam();
|
||||
|
||||
param.setName(nextParamName);
|
||||
// if (StringUtils.isNotBlank(chain)) {
|
||||
// param.addChain(chain);
|
||||
// }
|
||||
param.setDocumentation(nextParamDescription);
|
||||
param.setType(nextParameter.getParamType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSearchMethodBinding(Rest rest, RestResource resource, String resourceName, RuntimeResourceDefinition def, TreeSet<String> includes, SearchMethodBinding searchMethodBinding) {
|
||||
includes.addAll(searchMethodBinding.getIncludes());
|
||||
|
||||
|
@ -251,49 +312,24 @@ public class ServerConformanceProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleDynamicSearchMethodBinding(RestResource resource, RuntimeResourceDefinition def, TreeSet<String> includes, DynamicSearchMethodBinding searchMethodBinding) {
|
||||
includes.addAll(searchMethodBinding.getIncludes());
|
||||
/**
|
||||
* Sets the cache property (default is true). If set to true, the same response will be returned for each
|
||||
* invocation.
|
||||
* <p>
|
||||
* See the class documentation for an important note if you are extending this class
|
||||
* </p>
|
||||
*/
|
||||
public void setCache(boolean theCache) {
|
||||
myCache = theCache;
|
||||
}
|
||||
|
||||
List<RuntimeSearchParam> searchParameters = new ArrayList<RuntimeSearchParam>();
|
||||
searchParameters.addAll(searchMethodBinding.getSearchParams());
|
||||
sortRuntimeSearchParameters(searchParameters);
|
||||
|
||||
if (!searchParameters.isEmpty()) {
|
||||
|
||||
for (RuntimeSearchParam nextParameter : searchParameters) {
|
||||
|
||||
String nextParamName = nextParameter.getName();
|
||||
|
||||
// String chain = null;
|
||||
String nextParamUnchainedName = nextParamName;
|
||||
if (nextParamName.contains(".")) {
|
||||
// chain = nextParamName.substring(nextParamName.indexOf('.') + 1);
|
||||
nextParamUnchainedName = nextParamName.substring(0, nextParamName.indexOf('.'));
|
||||
}
|
||||
|
||||
String nextParamDescription = nextParameter.getDescription();
|
||||
|
||||
/*
|
||||
* If the parameter has no description, default to the one from the resource
|
||||
*/
|
||||
if (StringUtils.isBlank(nextParamDescription)) {
|
||||
RuntimeSearchParam paramDef = def.getSearchParam(nextParamUnchainedName);
|
||||
if (paramDef != null) {
|
||||
nextParamDescription = paramDef.getDescription();
|
||||
}
|
||||
}
|
||||
|
||||
RestResourceSearchParam param;
|
||||
param = resource.addSearchParam();
|
||||
|
||||
param.setName(nextParamName);
|
||||
// if (StringUtils.isNotBlank(chain)) {
|
||||
// param.addChain(chain);
|
||||
// }
|
||||
param.setDocumentation(nextParamDescription);
|
||||
param.setType(nextParameter.getParamType());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets the value of the "publisher" that will be placed in the generated conformance statement. As this
|
||||
* is a mandatory element, the value should not be null (although this is not enforced). The value defaults
|
||||
* to "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
*/
|
||||
public void setPublisher(String thePublisher) {
|
||||
myPublisher = thePublisher;
|
||||
}
|
||||
|
||||
private void sortRuntimeSearchParameters(List<RuntimeSearchParam> searchParameters) {
|
||||
|
@ -319,15 +355,4 @@ public class ServerConformanceProvider {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache property (default is true). If set to true, the same response will be returned for each
|
||||
* invocation.
|
||||
* <p>
|
||||
* See the class documentation for an important note if you are extending this class
|
||||
* </p>
|
||||
*/
|
||||
public void setCache(boolean theCache) {
|
||||
myCache = theCache;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@ import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
|
|||
public class ServerConformanceProviderTest {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerConformanceProviderTest.class);
|
||||
|
||||
private FhirContext myCtx = new FhirContext();
|
||||
|
||||
@Test
|
||||
public void testSearchParameterDocumentation() throws Exception {
|
||||
|
||||
|
@ -59,14 +60,34 @@ public class ServerConformanceProviderTest {
|
|||
}
|
||||
assertTrue(found);
|
||||
Conformance conformance = sc.getServerConformance();
|
||||
String conf = new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
|
||||
String conf = myCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||
ourLog.info(conf);
|
||||
|
||||
assertThat(conf, containsString("<documentation value=\"The patient's identifier (MRN or other card number)\"/>"));
|
||||
assertThat(conf, containsString("<type value=\"token\"/>"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testValidateGeneratedStatement() throws Exception {
|
||||
|
||||
RestfulServer rs = new RestfulServer();
|
||||
rs.setProviders(new MultiOptionalProvider());
|
||||
|
||||
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||
rs.setServerConformanceProvider(sc);
|
||||
|
||||
rs.init(null);
|
||||
|
||||
Conformance conformance = sc.getServerConformance();
|
||||
|
||||
myCtx.newValidator().validate(conformance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testMultiOptionalDocumentation() throws Exception {
|
||||
|
||||
|
|
|
@ -18,5 +18,11 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
Loading…
Reference in New Issue