Re-enable contains searches on the public HAPI FHIR server and improve
message formatting in HapiLocalizer
This commit is contained in:
parent
ed4da7c414
commit
a8c76450e5
|
@ -101,13 +101,36 @@ public class HapiLocalizer {
|
|||
|
||||
String formatString = getFormatString(theQualifiedKey);
|
||||
|
||||
format = new MessageFormat(formatString.trim());
|
||||
format = newMessageFormat(formatString);
|
||||
myKeyToMessageFormat.put(theQualifiedKey, format);
|
||||
return format.format(theParameters);
|
||||
}
|
||||
return getFormatString(theQualifiedKey);
|
||||
}
|
||||
|
||||
MessageFormat newMessageFormat(String theFormatString) {
|
||||
StringBuilder pattern = new StringBuilder(theFormatString.trim());
|
||||
|
||||
|
||||
for (int i = 0; i < (pattern.length()-1); i++) {
|
||||
if (pattern.charAt(i) == '{') {
|
||||
char nextChar = pattern.charAt(i+1);
|
||||
if (nextChar >= '0' && nextChar <= '9') {
|
||||
continue;
|
||||
}
|
||||
|
||||
pattern.replace(i, i+1, "'{'");
|
||||
int closeBraceIndex = pattern.indexOf("}", i);
|
||||
if (closeBraceIndex > 0) {
|
||||
i = closeBraceIndex;
|
||||
pattern.replace(i, i+1, "'}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new MessageFormat(pattern.toString());
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
for (String nextName : myBundleNames) {
|
||||
myBundle.add(ResourceBundle.getBundle(nextName));
|
||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.i18n;
|
|||
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.Set;
|
||||
|
@ -10,6 +11,15 @@ import org.junit.Test;
|
|||
|
||||
public class HapiLocalizerTest {
|
||||
|
||||
@Test
|
||||
public void testEscapePatterns() {
|
||||
HapiLocalizer loc = new HapiLocalizer();
|
||||
|
||||
assertEquals("some message", loc.newMessageFormat("some message").format(new Object[]{}));
|
||||
assertEquals("var1 {var2} var3 {var4}", loc.newMessageFormat("var1 {var2} var3 {var4}").format(new Object[]{}));
|
||||
assertEquals("var1 A var3 B", loc.newMessageFormat("var1 {0} var3 {1}").format(new Object[]{ "A", "B"}));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAllKeys() {
|
||||
|
|
|
@ -76,7 +76,7 @@ public class SearchParamPresenceSvcImpl implements ISearchParamPresenceSvc {
|
|||
toDelete.add(nextEntry.getValue());
|
||||
}
|
||||
}
|
||||
mySearchParamPresentDao.deleteInBatch(toDelete);
|
||||
mySearchParamPresentDao.deleteAll(toDelete);
|
||||
|
||||
// Add any that should be added
|
||||
List<SearchParamPresent> toAdd = new ArrayList<>();
|
||||
|
|
|
@ -398,7 +398,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
|
|||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
txTemplate.execute(t -> {
|
||||
theDao.deleteInBatch(link);
|
||||
theDao.deleteAll(link);
|
||||
return null;
|
||||
});
|
||||
|
||||
|
|
|
@ -2935,6 +2935,52 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
|||
assertThat(ids, containsInAnyOrder(pt2id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithContainsLowerCase() {
|
||||
myDaoConfig.setAllowContainsSearches(true);
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.addName().setFamily("abcdefghijk");
|
||||
String pt1id = myPatientDao.create(pt1).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.addName().setFamily("fghijk");
|
||||
String pt2id = myPatientDao.create(pt2).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Patient pt3 = new Patient();
|
||||
pt3.addName().setFamily("zzzzz");
|
||||
myPatientDao.create(pt3).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
|
||||
List<String> ids;
|
||||
SearchParameterMap map;
|
||||
IBundleProvider results;
|
||||
|
||||
// Contains = true
|
||||
map = new SearchParameterMap();
|
||||
map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(true));
|
||||
map.setLoadSynchronous(true);
|
||||
results = myPatientDao.search(map);
|
||||
ids = toUnqualifiedVersionlessIdValues(results);
|
||||
assertThat(ids, containsInAnyOrder(pt1id, pt2id));
|
||||
|
||||
// Contains = false
|
||||
map = new SearchParameterMap();
|
||||
map.add(Patient.SP_NAME, new StringParam("FGHIJK").setContains(false));
|
||||
map.setLoadSynchronous(true);
|
||||
results = myPatientDao.search(map);
|
||||
ids = toUnqualifiedVersionlessIdValues(results);
|
||||
assertThat(ids, containsInAnyOrder(pt2id));
|
||||
|
||||
// No contains
|
||||
map = new SearchParameterMap();
|
||||
map.add(Patient.SP_NAME, new StringParam("FGHIJK"));
|
||||
map.setLoadSynchronous(true);
|
||||
results = myPatientDao.search(map);
|
||||
ids = toUnqualifiedVersionlessIdValues(results);
|
||||
assertThat(ids, containsInAnyOrder(pt2id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithContainsDisabled() {
|
||||
myDaoConfig.setAllowContainsSearches(false);
|
||||
|
|
|
@ -37,8 +37,10 @@ import java.util.Set;
|
|||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.util.TestUtil;
|
||||
import ca.uhn.fhir.rest.api.PreferReturnEnum;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
@ -137,6 +139,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
|
||||
myDaoConfig.setCountSearchResultsUpTo(new DaoConfig().getCountSearchResultsUpTo());
|
||||
myDaoConfig.setSearchPreFetchThresholds(new DaoConfig().getSearchPreFetchThresholds());
|
||||
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
|
||||
|
||||
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(null);
|
||||
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(SearchCoordinatorSvcImpl.DEFAULT_SYNC_SIZE);
|
||||
|
@ -156,7 +159,42 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
myDaoConfig.setSearchPreFetchThresholds(new DaoConfig().getSearchPreFetchThresholds());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithContainsLowerCase() {
|
||||
myDaoConfig.setAllowContainsSearches(true);
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
pt1.addName().setFamily("Elizabeth");
|
||||
String pt1id = myPatientDao.create(pt1).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Patient pt2 = new Patient();
|
||||
pt2.addName().setFamily("fghijk");
|
||||
String pt2id = myPatientDao.create(pt2).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
Patient pt3 = new Patient();
|
||||
pt3.addName().setFamily("zzzzz");
|
||||
myPatientDao.create(pt3).getId().toUnqualifiedVersionless().getValue();
|
||||
|
||||
|
||||
Bundle output = ourClient
|
||||
.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.contains().value("ZAB"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
List<String> ids = output.getEntry().stream().map(t -> t.getResource().getIdElement().toUnqualifiedVersionless().getValue()).collect(Collectors.toList());
|
||||
assertThat(ids, containsInAnyOrder(pt1id));
|
||||
|
||||
output = ourClient
|
||||
.search()
|
||||
.forResource("Patient")
|
||||
.where(Patient.NAME.contains().value("zab"))
|
||||
.returnBundle(Bundle.class)
|
||||
.execute();
|
||||
ids = output.getEntry().stream().map(t -> t.getResource().getIdElement().toUnqualifiedVersionless().getValue()).collect(Collectors.toList());
|
||||
assertThat(ids, containsInAnyOrder(pt1id));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualPagingLinkOffsetDoesntReturnBeyondEnd() {
|
||||
|
|
|
@ -93,7 +93,7 @@ public class WebsocketWithCriteriaDstu3Test extends BaseResourceProviderDstu3Tes
|
|||
}
|
||||
|
||||
@Test
|
||||
public void createObservation() throws Exception {
|
||||
public void createObservation() {
|
||||
Observation observation = new Observation();
|
||||
CodeableConcept codeableConcept = new CodeableConcept();
|
||||
observation.setCode(codeableConcept);
|
||||
|
|
|
@ -46,7 +46,7 @@ import static org.apache.commons.lang3.StringUtils.left;
|
|||
* IDX_SP_STRING
|
||||
*/
|
||||
|
||||
// This one us used only for sorting
|
||||
// This is used for sorting, and for :contains queries currently
|
||||
@Index(name = "IDX_SP_STRING_HASH_IDENT", columnList = "HASH_IDENTITY"),
|
||||
|
||||
@Index(name = "IDX_SP_STRING_HASH_NRM", columnList = "HASH_NORM_PREFIX,SP_VALUE_NORMALIZED"),
|
||||
|
|
|
@ -61,6 +61,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
|||
retVal.setSubscriptionEnabled(true);
|
||||
retVal.setSubscriptionPollDelay(5000);
|
||||
retVal.setSubscriptionPurgeInactiveAfterMillis(DateUtils.MILLIS_PER_HOUR);
|
||||
retVal.setAllowContainsSearches(true);
|
||||
retVal.setAllowMultipleDelete(true);
|
||||
retVal.setAllowInlineMatchUrlReferences(true);
|
||||
retVal.setAllowExternalReferences(true);
|
||||
|
|
|
@ -52,6 +52,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
retVal.setSubscriptionEnabled(true);
|
||||
retVal.setSubscriptionPollDelay(5000);
|
||||
retVal.setSubscriptionPurgeInactiveAfterMillis(DateUtils.MILLIS_PER_HOUR);
|
||||
retVal.setAllowContainsSearches(true);
|
||||
retVal.setAllowMultipleDelete(true);
|
||||
retVal.setAllowInlineMatchUrlReferences(true);
|
||||
retVal.setAllowExternalReferences(true);
|
||||
|
|
|
@ -52,6 +52,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
|||
retVal.setSubscriptionEnabled(true);
|
||||
retVal.setSubscriptionPollDelay(5000);
|
||||
retVal.setSubscriptionPurgeInactiveAfterMillis(DateUtils.MILLIS_PER_HOUR);
|
||||
retVal.setAllowContainsSearches(true);
|
||||
retVal.setAllowMultipleDelete(true);
|
||||
retVal.setAllowInlineMatchUrlReferences(true);
|
||||
retVal.setAllowExternalReferences(true);
|
||||
|
|
|
@ -77,6 +77,10 @@
|
|||
A new config setting has been added to the JPA DaoConfig that disables validation
|
||||
of the resource type for target resources in references.
|
||||
</action>
|
||||
<action type="add">
|
||||
HapiLocalizer can now handle message patterns with braces that aren't a part of a
|
||||
message format expression. E.g. "Here is an {example}".
|
||||
</action>
|
||||
</release>
|
||||
<release version="3.7.0" date="2019-02-06" description="Gale">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue