More work on #52

This commit is contained in:
jamesagnew 2014-11-19 08:17:48 -05:00
parent 8264f06ef7
commit 9d4a56bf47
4 changed files with 281 additions and 45 deletions

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.dao;
import static org.apache.commons.lang3.StringUtils.*;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Collection;
@ -79,6 +80,7 @@ import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.parser.IParser;
@ -306,7 +308,6 @@ public abstract class BaseFhirDao implements IDao {
ArrayList<ResourceLink> retVal = new ArrayList<ResourceLink>();
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
FhirTerser t = getContext().newTerser();
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != SearchParamTypeEnum.REFERENCE) {
continue;
@ -322,19 +323,7 @@ public abstract class BaseFhirDao implements IDao {
multiType = true;
}
List<Object> values = new ArrayList<Object>();
String[] nextPathsSplit = nextPathsUnsplit.split("\\|");
for (String nextPath : nextPathsSplit) {
String nextPathTrimmed = nextPath.trim();
try {
values.addAll(t.getValues(theResource, nextPathTrimmed));
} catch (Exception e) {
ourLog.warn("Failed to index values from path[{}] in resource type[{}]: ", nextPathTrimmed, def.getName(), e.toString());
}
}
for (Object nextObject : values) {
for (Object nextObject : extractValues(nextPathsUnsplit, theResource)) {
if (nextObject == null) {
continue;
}
@ -395,11 +384,26 @@ public abstract class BaseFhirDao implements IDao {
return retVal;
}
private List<Object> extractValues(String thePaths, IResource theResource) {
List<Object> values = new ArrayList<Object>();
String[] nextPathsSplit = thePaths.split("\\|");
FhirTerser t = getContext().newTerser();
for (String nextPath : nextPathsSplit) {
String nextPathTrimmed = nextPath.trim();
try {
values.addAll(t.getValues(theResource, nextPathTrimmed));
} catch (Exception e) {
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
ourLog.warn("Failed to index values from path[{}] in resource type[{}]: ", nextPathTrimmed, def.getName(), e.toString());
}
}
return values;
}
protected List<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IResource theResource) {
ArrayList<ResourceIndexedSearchParamDate> retVal = new ArrayList<ResourceIndexedSearchParamDate>();
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
FhirTerser t = getContext().newTerser();
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != SearchParamTypeEnum.DATE) {
continue;
@ -415,8 +419,7 @@ public abstract class BaseFhirDao implements IDao {
multiType = true;
}
List<Object> values = t.getValues(theResource, nextPath);
for (Object nextObject : values) {
for (Object nextObject : extractValues(nextPath, theResource)) {
if (nextObject == null) {
continue;
}
@ -457,7 +460,6 @@ public abstract class BaseFhirDao implements IDao {
ArrayList<ResourceIndexedSearchParamNumber> retVal = new ArrayList<ResourceIndexedSearchParamNumber>();
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
FhirTerser t = getContext().newTerser();
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != SearchParamTypeEnum.NUMBER) {
continue;
@ -468,8 +470,7 @@ public abstract class BaseFhirDao implements IDao {
continue;
}
List<Object> values = t.getValues(theResource, nextPath);
for (Object nextObject : values) {
for (Object nextObject : extractValues(nextPath, theResource)) {
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
continue;
}
@ -521,6 +522,15 @@ public abstract class BaseFhirDao implements IDao {
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, nextValue.getValue().getValue());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
} else if (nextObject instanceof IntegerDt) {
IntegerDt nextValue = (IntegerDt) nextObject;
if (nextValue.getValue()==null) {
continue;
}
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(resourceName, new BigDecimal(nextValue.getValue()));
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
} else {
if (!multiType) {
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
@ -540,7 +550,6 @@ public abstract class BaseFhirDao implements IDao {
ArrayList<ResourceIndexedSearchParamQuantity> retVal = new ArrayList<ResourceIndexedSearchParamQuantity>();
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
FhirTerser t = getContext().newTerser();
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != SearchParamTypeEnum.QUANTITY) {
continue;
@ -551,8 +560,7 @@ public abstract class BaseFhirDao implements IDao {
continue;
}
List<Object> values = t.getValues(theResource, nextPath);
for (Object nextObject : values) {
for (Object nextObject : extractValues(nextPath, theResource)) {
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
continue;
}
@ -592,7 +600,6 @@ public abstract class BaseFhirDao implements IDao {
ArrayList<ResourceIndexedSearchParamString> retVal = new ArrayList<ResourceIndexedSearchParamString>();
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
FhirTerser t = getContext().newTerser();
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != SearchParamTypeEnum.STRING) {
continue;
@ -604,8 +611,7 @@ public abstract class BaseFhirDao implements IDao {
continue;
}
List<Object> values = t.getValues(theResource, nextPath);
for (Object nextObject : values) {
for (Object nextObject : extractValues(nextPath, theResource)) {
if (nextObject == null || ((IDatatype) nextObject).isEmpty()) {
continue;
}
@ -682,7 +688,6 @@ public abstract class BaseFhirDao implements IDao {
ArrayList<BaseResourceIndexedSearchParam> retVal = new ArrayList<BaseResourceIndexedSearchParam>();
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
FhirTerser t = getContext().newTerser();
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
if (nextSpDef.getParamType() != SearchParamTypeEnum.TOKEN) {
continue;
@ -698,10 +703,10 @@ public abstract class BaseFhirDao implements IDao {
multiType = true;
}
List<Object> values = t.getValues(theResource, nextPath);
List<String> systems = new ArrayList<String>();
List<String> codes = new ArrayList<String>();
for (Object nextObject : values) {
for (Object nextObject : extractValues(nextPath, theResource)) {
if (nextObject instanceof IdentifierDt) {
IdentifierDt nextValue = (IdentifierDt) nextObject;
if (nextValue.isEmpty()) {

View File

@ -1,10 +1,7 @@
package ca.uhn.fhir.jpa.test;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.Date;
@ -68,7 +65,6 @@ public class CompleteResourceProviderTest {
private static IFhirResourceDao<Observation> ourObservationDao;
private static IFhirResourceDao<Patient> ourPatientDao;
private static IFhirResourceDao<Questionnaire> ourQuestionnaireDao;
private static IFhirResourceDao<ImagingStudy> ourImagingStudyDao;
private static Server ourServer;
// private static JpaConformanceProvider ourConfProvider;
@ -91,6 +87,41 @@ public class CompleteResourceProviderTest {
}
/**
* See issue #52
*/
@Test
public void testDocumentManifestResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentManifest.class).execute().size();
String resBody = IOUtils.toString(CompleteResourceProviderTest.class.getResource("/documentmanifest.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentManifest.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
*/
@Test
public void testDocumentReferenceResources() throws Exception {
IGenericClient client = ourClient;
int initialSize = client.search().forResource(DocumentReference.class).execute().size();
String resBody = IOUtils.toString(CompleteResourceProviderTest.class.getResource("/documentreference.json"));
client.create().resource(resBody).execute();
int newSize = client.search().forResource(DocumentReference.class).execute().size();
assertEquals(1, newSize - initialSize);
}
/**
* See issue #52
@ -206,7 +237,7 @@ public class CompleteResourceProviderTest {
p1.getText().getDiv().setValueAsString("<div>HELLO WORLD</div>");
p1.addIdentifier().setSystem("urn:system").setValue("testSaveAndRetrieveExistingNarrative01");
IdDt newId = ourClient.create(p1).getId();
IdDt newId = ourClient.create().resource(p1).execute().getId();
Patient actual = ourClient.read(Patient.class, newId);
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">HELLO WORLD</div>", actual.getText().getDiv().getValueAsString());
@ -238,7 +269,7 @@ public class CompleteResourceProviderTest {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testSearchByResourceChain01");
IdDt newId = ourClient.create(p1).getId();
IdDt newId = ourClient.create().resource(p1).execute().getId();
Patient actual = ourClient.read(Patient.class, newId);
assertThat(actual.getText().getDiv().getValueAsString(), containsString("<td>Identifier</td><td>testSearchByResourceChain01</td>"));
@ -252,12 +283,12 @@ public class CompleteResourceProviderTest {
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testSearchByIdentifier01");
p1.addName().addFamily("testSearchByIdentifierFamily01").addGiven("testSearchByIdentifierGiven01");
IdDt p1Id = ourClient.create(p1).getId();
IdDt p1Id = ourClient.create().resource(p1).execute().getId();
Patient p2 = new Patient();
p2.addIdentifier().setSystem("urn:system").setValue("testSearchByIdentifier02");
p2.addName().addFamily("testSearchByIdentifierFamily01").addGiven("testSearchByIdentifierGiven02");
ourClient.create(p2).getId();
ourClient.create().resource(p2).execute().getId();
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testSearchByIdentifier01")).encodedJson().prettyPrint().execute();
assertEquals(1, actual.size());
@ -270,7 +301,7 @@ public class CompleteResourceProviderTest {
Patient p1 = new Patient();
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
IdDt p1Id = ourClient.create(p1).getId();
IdDt p1Id = ourClient.create().resource(p1).execute().getId();
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint()
.execute();
@ -286,19 +317,19 @@ public class CompleteResourceProviderTest {
Organization o1 = new Organization();
o1.setName("testSearchByResourceChainName01");
IdDt o1id = ourClient.create(o1).getId();
IdDt o1id = ourClient.create().resource(o1).execute().getId();
Patient p1 = new Patient();
p1.addIdentifier().setSystem("urn:system").setValue("testSearchByResourceChain01");
p1.addName().addFamily("testSearchByResourceChainFamily01").addGiven("testSearchByResourceChainGiven01");
p1.setManagingOrganization(new ResourceReferenceDt(o1id));
IdDt p1Id = ourClient.create(p1).getId();
IdDt p1Id = ourClient.create().resource(p1).execute().getId();
//@formatter:off
Bundle actual = ourClient.search()
.forResource(Patient.class)
.where(Patient.PROVIDER.hasId(o1id.getIdPart()))
.encodedJson().andLogRequestAndResponse(true).prettyPrint().execute();
.encodedJson().prettyPrint().execute();
//@formatter:on
assertEquals(1, actual.size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getId().getIdPart());
@ -307,7 +338,7 @@ public class CompleteResourceProviderTest {
actual = ourClient.search()
.forResource(Patient.class)
.where(Patient.PROVIDER.hasId(o1id.getValue()))
.encodedJson().andLogRequestAndResponse(true).prettyPrint().execute();
.encodedJson().prettyPrint().execute();
//@formatter:on
assertEquals(1, actual.size());
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getId().getIdPart());
@ -324,7 +355,7 @@ public class CompleteResourceProviderTest {
p1.setManagingOrganization(new ResourceReferenceDt("Organization/1323123232349875324987529835"));
try {
ourClient.create(p1).getId();
ourClient.create().resource(p1).execute().getId();
fail();
} catch (InvalidRequestException e) {
assertThat(e.getMessage(), containsString("Organization/1323123232349875324987529835"));

View File

@ -0,0 +1,60 @@
{
"resourceType" : "DocumentManifest",
"text" : {
"status" : "generated",
"div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\">Text</div>"
},
"contained" : [
{
"resourceType" : "Practitioner",
"id" : "a1",
"name" : {
"family" : [
"Dopplemeyer"
],
"given" : [
"Sherry"
]
},
"telecom" : [
{
"system" : "email",
"value" : "john.doe@healthcare.example.org"
}
],
"organization" : {
"display" : "Cleveland Clinic"
},
"role" : [
{
"text" : "Primary Surgon"
}
],
"specialty" : [
{
"text" : "Orthopedic"
}
]
}
],
"masterIdentifier" : {
"system" : "http://example.org/documents",
"value" : "23425234234-2346"
},
"subject" : [
],
"type" : {
"text" : "History and Physical"
},
"author" : [
{
"reference" : "#a1"
}
],
"created" : "2004-12-25T23:50:50",
"source" : "urn:oid:1.3.6.1.4.1.21367.2009.1.2.1",
"status" : "current",
"description" : "Physical",
"content" : [
]
}

View File

@ -0,0 +1,140 @@
{
"resourceType" : "DocumentReference",
"text" : {
"status" : "generated",
"div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\">&#xA; <p>&#xA; <b>Generated Narrative</b>&#xA; </p>&#xA; <p>&#xA; <b>masterIdentifier</b>: urn:oid:1.3.6.1.4.1.21367.2005.3.7&#xA; </p>&#xA; <p>&#xA; <b>subject</b>: &#xA; <a href=\"Patient/xcda\">MRN = 12345 (usual); Henry Levin ; Male; birthDate: 24-Sep 1932; active</a>&#xA; </p>&#xA; <p>&#xA; <b>type</b>: &#xA; <span title=\"Codes: {http://loinc.org 34108-1}\">Outpatient Note</span>&#xA; </p>&#xA; <p>&#xA; <b>author</b>: Sherry Dopplemeyer ; Primary Surgon; Orthopedic, Gerald Smitty ; Attending; Orthopedic&#xA; </p>&#xA; <p>&#xA; <b>created</b>: 24-Dec 2005 9:35&#xA; </p>&#xA; <p>&#xA; <b>indexed</b>: 24-Dec 2005 9:43&#xA; </p>&#xA; <p>&#xA; <b>status</b>: current&#xA; </p>&#xA; <p>&#xA; <b>description</b>: Physical&#xA; </p>&#xA; <p>&#xA; <b>confidentiality</b>: &#xA; <span title=\"Codes: {http://ihe.net/xds/connectathon/confidentialityCodes 1.3.6.1.4.1.21367.2006.7.101}\">Clinical-Staff</span>&#xA; </p>&#xA; <p>&#xA; <b>primaryLanguage</b>: en-US&#xA; </p>&#xA; <p>&#xA; <b>mimeType</b>: application/hl7-v3+xml&#xA; </p>&#xA; <p>&#xA; <b>size</b>: 3654&#xA; </p>&#xA; <p>&#xA; <b>hash</b>: da39a3ee5e6b4b0d3255bfef95601890afd80709&#xA; </p>&#xA; <p>&#xA; <b>location</b>: &#xA; <a href=\"http://example.org/xds/mhd/Binary/@07a6483f-732b-461e-86b6-edb665c45510\">http://example.org/xds/mhd/Binary/@07a6483f-732b-461e-86b6-edb665c45510</a>&#xA; </p>&#xA; <h3>Contexts</h3>&#xA; <table class=\"grid\">&#xA; <tr>&#xA; <td>&#xA; <b>Event</b>&#xA; </td>&#xA; <td>&#xA; <b>Period</b>&#xA; </td>&#xA; <td>&#xA; <b>FacilityType</b>&#xA; </td>&#xA; </tr>&#xA; <tr>&#xA; <td>&#xA; <span title=\"Codes: {http://ihe.net/xds/connectathon/eventCodes T-D8200}\">Arm</span>&#xA; </td>&#xA; <td>23-Dec 2004 8:0 --&gt; 23-Dec 2004 8:1</td>&#xA; <td>&#xA; <span title=\"Codes: {http://www.ihe.net/xds/connectathon/healthcareFacilityTypeCodes Outpatient}\">Outpatient</span>&#xA; </td>&#xA; </tr>&#xA; </table>&#xA; </div>"
},
"contained" : [
{
"resourceType" : "Practitioner",
"id" : "a1",
"name" : {
"family" : [
"Dopplemeyer"
],
"given" : [
"Sherry"
]
},
"telecom" : [
{
"system" : "email",
"value" : "john.doe@healthcare.example.org"
}
],
"organization" : {
"display" : "Cleveland Clinic"
},
"role" : [
{
"text" : "Primary Surgon"
}
],
"specialty" : [
{
"text" : "Orthopedic"
}
]
},
{
"resourceType" : "Practitioner",
"id" : "a2",
"name" : {
"family" : [
"Smitty"
],
"given" : [
"Gerald"
]
},
"telecom" : [
{
"system" : "email",
"value" : "john.doe@healthcare.example.org"
}
],
"organization" : {
"display" : "Cleveland Clinic"
},
"role" : [
{
"text" : "Attending"
}
],
"specialty" : [
{
"text" : "Orthopedic"
}
]
}
],
"masterIdentifier" : {
"system" : "urn:ietf:rfc:3986",
"value" : "urn:oid:1.3.6.1.4.1.21367.2005.3.7"
},
"subject" : {
},
"type" : {
"coding" : [
{
"system" : "http://loinc.org",
"code" : "34108-1",
"display" : "Outpatient Note"
}
]
},
"author" : [
{
"reference" : "#a1"
},
{
"reference" : "#a2"
}
],
"created" : "2005-12-24T09:35:00+11:00",
"indexed" : "2005-12-24T09:43:41+11:00",
"status" : "current",
"description" : "Physical",
"confidentiality" : [
{
"coding" : [
{
"system" : "http://ihe.net/xds/connectathon/confidentialityCodes",
"code" : "1.3.6.1.4.1.21367.2006.7.101",
"display" : "Clinical-Staff"
}
]
}
],
"primaryLanguage" : "en-US",
"mimeType" : "application/hl7-v3+xml",
"size" : 3654,
"hash" : "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"location" : "http://example.org/xds/mhd/Binary/@07a6483f-732b-461e-86b6-edb665c45510",
"context" : {
"event" : [
{
"coding" : [
{
"system" : "http://ihe.net/xds/connectathon/eventCodes",
"code" : "T-D8200",
"display" : "Arm"
}
]
}
],
"period" : {
"start" : "2004-12-23T08:00:00",
"end" : "2004-12-23T08:01:00"
},
"facilityType" : {
"coding" : [
{
"system" : "http://www.ihe.net/xds/connectathon/healthcareFacilityTypeCodes",
"code" : "Outpatient",
"display" : "Outpatient"
}
]
}
}
}