Support Questionnaire.answers indexing in JPA server

This commit is contained in:
James Agnew 2015-06-18 18:51:11 -04:00
parent 12f3cfcab8
commit 84571f993c
4 changed files with 94 additions and 65 deletions

View File

@ -60,6 +60,7 @@ import ca.uhn.fhir.model.dstu2.composite.PeriodDt;
import ca.uhn.fhir.model.dstu2.composite.QuantityDt;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Patient.Communication;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ -311,8 +312,17 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
}
String nextPath = nextSpDef.getPath();
String resourceName = nextSpDef.getName();
if (isBlank(nextPath)) {
// TODO: implement phonetic, and any others that have no path
if ("Questionnaire".equals(def.getName()) && nextSpDef.getName().equals("title")) {
Questionnaire q = (Questionnaire) theResource;
String title = q.getGroup().getTitle();
addSearchTerm(theEntity, retVal, resourceName, title);
}
continue;
}
@ -321,7 +331,6 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
continue;
}
String resourceName = nextSpDef.getName();
boolean multiType = false;
if (nextPath.endsWith("[x]")) {
multiType = true;
@ -330,13 +339,7 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
if (nextObject instanceof IPrimitiveDatatype<?>) {
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
String searchTerm = nextValue.getValueAsString();
if (searchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
searchTerm = searchTerm.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
}
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, BaseFhirDao.normalizeString(searchTerm), searchTerm);
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
addSearchTerm(theEntity, retVal, resourceName, searchTerm);
} else {
if (nextObject instanceof BaseHumanNameDt) {
ArrayList<StringDt> allNames = new ArrayList<StringDt>();
@ -344,12 +347,7 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
allNames.addAll(nextHumanName.getFamily());
allNames.addAll(nextHumanName.getGiven());
for (StringDt nextName : allNames) {
if (nextName.isEmpty()) {
continue;
}
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, BaseFhirDao.normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
addSearchTerm(theEntity, retVal, resourceName, nextName.getValue());
}
} else if (nextObject instanceof AddressDt) {
ArrayList<StringDt> allNames = new ArrayList<StringDt>();
@ -360,19 +358,12 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
allNames.add(nextAddress.getCountryElement());
allNames.add(nextAddress.getPostalCodeElement());
for (StringDt nextName : allNames) {
if (nextName.isEmpty()) {
continue;
}
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, BaseFhirDao.normalizeString(nextName.getValueAsString()), nextName.getValueAsString());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
addSearchTerm(theEntity, retVal, resourceName, nextName.getValue());
}
} else if (nextObject instanceof ContactPointDt) {
ContactPointDt nextContact = (ContactPointDt) nextObject;
if (nextContact.getValueElement().isEmpty() == false) {
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, BaseFhirDao.normalizeString(nextContact.getValueElement().getValueAsString()), nextContact.getValue());
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
addSearchTerm(theEntity, retVal, resourceName, nextContact.getValue());
}
} else {
if (!multiType) {
@ -388,6 +379,19 @@ class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implements ISea
return retVal;
}
private void addSearchTerm(ResourceTable theEntity, ArrayList<ResourceIndexedSearchParamString> retVal, String resourceName, String searchTerm) {
if (isBlank(searchTerm)) {
return;
}
if (searchTerm.length() > ResourceIndexedSearchParamString.MAX_LENGTH) {
searchTerm = searchTerm.substring(0, ResourceIndexedSearchParamString.MAX_LENGTH);
}
ResourceIndexedSearchParamString nextEntity = new ResourceIndexedSearchParamString(resourceName, BaseFhirDao.normalizeString(searchTerm), searchTerm);
nextEntity.setResource(theEntity);
retVal.add(nextEntity);
}
/*
* (non-Javadoc)
*

View File

@ -59,6 +59,8 @@ import ca.uhn.fhir.model.dstu2.resource.Location;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.resource.Questionnaire;
import ca.uhn.fhir.model.dstu2.resource.QuestionnaireAnswers;
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum;
import ca.uhn.fhir.model.dstu2.valueset.QuantityComparatorEnum;
@ -71,6 +73,7 @@ import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.gclient.StringClientParam;
import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
@ -101,7 +104,27 @@ public class FhirResourceDaoDstu2Test {
private static IFhirResourceDao<Organization> ourOrganizationDao;
private static IFhirResourceDao<Patient> ourPatientDao;
private static IFhirSystemDao<Bundle> ourSystemDao;
private static IFhirResourceDao<Questionnaire> ourQuestionnaireDao;
@SuppressWarnings("unused")
private static IFhirResourceDao<QuestionnaireAnswers> ourQuestionnaireAnswersDao;
@Test
public void testQuestionnaireTitleGetsIndexed() {
Questionnaire q = new Questionnaire();
q.getGroup().setTitle("testQuestionnaireTitleGetsIndexedQ_TITLE");
IdDt qid1 = ourQuestionnaireDao.create(q).getId().toUnqualifiedVersionless();
q = new Questionnaire();
q.getGroup().setTitle("testQuestionnaireTitleGetsIndexedQ_NOTITLE");
IdDt qid2 = ourQuestionnaireDao.create(q).getId().toUnqualifiedVersionless();
IBundleProvider results = ourQuestionnaireDao.search("title", new StringParam("testQuestionnaireTitleGetsIndexedQ_TITLE"));
assertEquals(1, results.size());
assertEquals(qid1, results.getResources(0, 1).get(0).getIdElement().toUnqualifiedVersionless());
assertNotEquals(qid2, results.getResources(0, 1).get(0).getIdElement().toUnqualifiedVersionless());
}
@Test
public void testChoiceParamConcept() {
Observation o1 = new Observation();
@ -2534,6 +2557,8 @@ public class FhirResourceDaoDstu2Test {
ourLocationDao = ourCtx.getBean("myLocationDaoDstu2", IFhirResourceDao.class);
ourEncounterDao = ourCtx.getBean("myEncounterDaoDstu2", IFhirResourceDao.class);
ourSystemDao = ourCtx.getBean("mySystemDaoDstu2", IFhirSystemDao.class);
ourQuestionnaireDao = ourCtx.getBean("myQuestionnaireDaoDstu2", IFhirResourceDao.class);
ourQuestionnaireAnswersDao = ourCtx.getBean("myQuestionnaireAnswersDaoDstu2", IFhirResourceDao.class);
ourFhirCtx = ourCtx.getBean(FhirContext.class);
}

View File

@ -1,20 +1,23 @@
package ca.uhn.fhir.jpa.provider;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
@ -58,7 +61,6 @@ import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.resource.Condition;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticOrder;
import ca.uhn.fhir.model.dstu2.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu2.resource.DocumentManifest;
import ca.uhn.fhir.model.dstu2.resource.DocumentReference;
import ca.uhn.fhir.model.dstu2.resource.Encounter;
@ -80,9 +82,7 @@ import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.gclient.IQuery;
import ca.uhn.fhir.rest.gclient.IReadExecutable;
import ca.uhn.fhir.rest.gclient.StringClientParam;
import ca.uhn.fhir.rest.gclient.TokenClientParam;
import ca.uhn.fhir.rest.server.Constants;
@ -133,6 +133,34 @@ public class ResourceProviderDstu2Test {
}
}
@Test
public void testBundleCreate() throws Exception {
IGenericClient client = ourClient;
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/document-father.json"));
IdDt id = client.create().resource(resBody).execute().getId();
ourLog.info("Created: {}", id);
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = client.read().resource(ca.uhn.fhir.model.dstu2.resource.Bundle.class).withId(id).execute();
ourLog.info(ourFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
}
@Test
public void testBundleCreateWithTypeTransaction() throws Exception {
IGenericClient client = ourClient;
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/document-father.json"));
resBody = resBody.replace("\"type\": \"document\"", "\"type\": \"transaction\"");
try {
client.create().resource(resBody).execute().getId();
fail();
} catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), containsString("Unable to store a Bundle resource on this server with a Bundle.type value other than 'document' - Value was: transaction"));
}
}
@Test
public void testCountParam() throws Exception {
// NB this does not get used- The paging provider has its own limits built in
@ -411,34 +439,6 @@ public class ResourceProviderDstu2Test {
}
@Test
public void testBundleCreate() throws Exception {
IGenericClient client = ourClient;
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/document-father.json"));
IdDt id = client.create().resource(resBody).execute().getId();
ourLog.info("Created: {}", id);
ca.uhn.fhir.model.dstu2.resource.Bundle bundle = client.read().resource(ca.uhn.fhir.model.dstu2.resource.Bundle.class).withId(id).execute();
ourLog.info(ourFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
}
@Test
public void testBundleCreateWithTypeTransaction() throws Exception {
IGenericClient client = ourClient;
String resBody = IOUtils.toString(ResourceProviderDstu2Test.class.getResource("/document-father.json"));
resBody = resBody.replace("\"type\": \"document\"", "\"type\": \"transaction\"");
try {
client.create().resource(resBody).execute().getId();
fail();
} catch (UnprocessableEntityException e) {
assertThat(e.getMessage(), containsString("Unable to store a Bundle resource on this server with a Bundle.type value other than 'document' - Value was: transaction"));
}
}
/**
* See #147
*/
@ -472,9 +472,6 @@ public class ResourceProviderDstu2Test {
ourLog.info("$everything: " + ids.toString());
assertFalse(ids.toString(), dupes);
// Default size
assertEquals(10, ids.size());
}
/*

View File

@ -105,6 +105,9 @@
<action type="add">
Server in DSTU2 mode now indicates that whether it has support for Transaction operation or not. Thanks to Kevin Paschke for pointing out that this wasn't working!
</action>
<action type="add">
Questionnaire.title now gets correctly indexed in JPA server (it has no path, so it is a special case)
</action>
</release>
<release version="1.0" date="2015-May-8">
<action type="add">