Add new indexing extractor method
This commit is contained in:
parent
27959614d8
commit
a5257f0fa8
|
@ -117,6 +117,23 @@ public class SearchParamExtractorR4Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExtractSearchParamTokenTest() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addIdentifier().setSystem("sys").setValue("val");
|
||||||
|
|
||||||
|
SearchParamExtractorR4 extractor = new SearchParamExtractorR4(new ModelConfig(), ourCtx, ourValidationSupport, mySearchParamRegistry);
|
||||||
|
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam("Patient", Patient.SP_IDENTIFIER);
|
||||||
|
assertNotNull(param);
|
||||||
|
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> params = extractor.extractSearchParamTokens(p, param);
|
||||||
|
assertEquals(1, params.size());
|
||||||
|
ResourceIndexedSearchParamToken paramValue = (ResourceIndexedSearchParamToken) params.iterator().next();
|
||||||
|
assertEquals("identifier", paramValue.getParamName());
|
||||||
|
assertEquals("sys", paramValue.getSystem());
|
||||||
|
assertEquals("val", paramValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExtensionContainingReference() {
|
public void testExtensionContainingReference() {
|
||||||
String path = "Patient.extension('http://patext').value.as(Reference)";
|
String path = "Patient.extension('http://patext').value.as(Reference)";
|
||||||
|
|
|
@ -186,7 +186,19 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource) {
|
public SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource) {
|
||||||
|
IExtractor<BaseResourceIndexedSearchParam> extractor = createTokenExtractor(theResource);
|
||||||
|
return extractSearchParams(theResource, extractor, RestSearchParameterTypeEnum.TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource, RuntimeSearchParam theSearchParam) {
|
||||||
|
IExtractor<BaseResourceIndexedSearchParam> extractor = createTokenExtractor(theResource);
|
||||||
|
SearchParamSet<BaseResourceIndexedSearchParam> setToPopulate = new SearchParamSet<>();
|
||||||
|
extractSearchParam(theSearchParam, theResource, extractor, setToPopulate);
|
||||||
|
return setToPopulate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IExtractor<BaseResourceIndexedSearchParam> createTokenExtractor(IBaseResource theResource) {
|
||||||
String resourceTypeName = toRootTypeName(theResource);
|
String resourceTypeName = toRootTypeName(theResource);
|
||||||
String useSystem;
|
String useSystem;
|
||||||
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||||
|
@ -204,85 +216,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IExtractor<BaseResourceIndexedSearchParam> extractor = (params, searchParam, value, path) -> {
|
return new TokenExtractor(resourceTypeName, useSystem);
|
||||||
|
|
||||||
// DSTU3+
|
|
||||||
if (value instanceof IBaseEnumeration<?>) {
|
|
||||||
IBaseEnumeration<?> obj = (IBaseEnumeration<?>) value;
|
|
||||||
String system = extractSystem(obj);
|
|
||||||
String code = obj.getValueAsString();
|
|
||||||
createTokenIndexIfNotBlank(resourceTypeName, params, searchParam, system, code);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DSTU2 only
|
|
||||||
if (value instanceof BoundCodeDt) {
|
|
||||||
BoundCodeDt boundCode = (BoundCodeDt) value;
|
|
||||||
Enum valueAsEnum = boundCode.getValueAsEnum();
|
|
||||||
String system = null;
|
|
||||||
if (valueAsEnum != null) {
|
|
||||||
//noinspection unchecked
|
|
||||||
system = boundCode.getBinder().toSystemString(valueAsEnum);
|
|
||||||
}
|
|
||||||
String code = boundCode.getValueAsString();
|
|
||||||
createTokenIndexIfNotBlank(resourceTypeName, params, searchParam, system, code);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value instanceof IPrimitiveType) {
|
|
||||||
IPrimitiveType<?> nextValue = (IPrimitiveType<?>) value;
|
|
||||||
String systemAsString = null;
|
|
||||||
String valueAsString = nextValue.getValueAsString();
|
|
||||||
if ("CodeSystem.concept.code".equals(path)) {
|
|
||||||
systemAsString = useSystem;
|
|
||||||
} else if ("ValueSet.codeSystem.concept.code".equals(path)) {
|
|
||||||
systemAsString = useSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
createTokenIndexIfNotBlank(resourceTypeName, params, searchParam, systemAsString, valueAsString);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (path) {
|
|
||||||
case "Patient.communication":
|
|
||||||
addToken_PatientCommunication(resourceTypeName, params, searchParam, value);
|
|
||||||
return;
|
|
||||||
case "Consent.source":
|
|
||||||
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
|
|
||||||
return;
|
|
||||||
case "Location.position":
|
|
||||||
addCoords_Position(resourceTypeName, params, searchParam, value);
|
|
||||||
return;
|
|
||||||
case "StructureDefinition.context":
|
|
||||||
// TODO: implement this
|
|
||||||
ourLog.warn("StructureDefinition context indexing not currently supported");
|
|
||||||
return;
|
|
||||||
case "CapabilityStatement.rest.security":
|
|
||||||
addToken_CapabilityStatementRestSecurity(resourceTypeName, params, searchParam, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String nextType = toRootTypeName(value);
|
|
||||||
switch (nextType) {
|
|
||||||
case "Identifier":
|
|
||||||
addToken_Identifier(resourceTypeName, params, searchParam, value);
|
|
||||||
break;
|
|
||||||
case "CodeableConcept":
|
|
||||||
addToken_CodeableConcept(resourceTypeName, params, searchParam, value);
|
|
||||||
break;
|
|
||||||
case "Coding":
|
|
||||||
addToken_Coding(resourceTypeName, params, searchParam, value);
|
|
||||||
break;
|
|
||||||
case "ContactPoint":
|
|
||||||
addToken_ContactPoint(resourceTypeName, params, searchParam, value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return extractSearchParams(theResource, extractor, RestSearchParameterTypeEnum.TOKEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -798,25 +732,29 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String nextPathUnsplit = nextSpDef.getPath();
|
extractSearchParam(nextSpDef, theResource, theExtractor, retVal);
|
||||||
if (isBlank(nextPathUnsplit)) {
|
}
|
||||||
continue;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] splitPaths = split(nextPathUnsplit);
|
private <T> void extractSearchParam(RuntimeSearchParam theSearchParameterDef, IBaseResource theResource, IExtractor<T> theExtractor, SearchParamSet<T> theSetToPopulate) {
|
||||||
for (String nextPath : splitPaths) {
|
String nextPathUnsplit = theSearchParameterDef.getPath();
|
||||||
nextPath = trim(nextPath);
|
if (isBlank(nextPathUnsplit)) {
|
||||||
for (IBase nextObject : extractValues(nextPath, theResource)) {
|
return;
|
||||||
if (nextObject != null) {
|
}
|
||||||
String typeName = toRootTypeName(nextObject);
|
|
||||||
if (!myIgnoredForSearchDatatypes.contains(typeName)) {
|
String[] splitPaths = split(nextPathUnsplit);
|
||||||
theExtractor.extract(retVal, nextSpDef, nextObject, nextPath);
|
for (String nextPath : splitPaths) {
|
||||||
}
|
nextPath = trim(nextPath);
|
||||||
|
for (IBase nextObject : extractValues(nextPath, theResource)) {
|
||||||
|
if (nextObject != null) {
|
||||||
|
String typeName = toRootTypeName(nextObject);
|
||||||
|
if (!myIgnoredForSearchDatatypes.contains(typeName)) {
|
||||||
|
theExtractor.extract(theSetToPopulate, theSearchParameterDef, nextObject, nextPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toRootTypeName(IBase nextObject) {
|
private String toRootTypeName(IBase nextObject) {
|
||||||
|
@ -1032,6 +970,95 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TokenExtractor implements IExtractor<BaseResourceIndexedSearchParam> {
|
||||||
|
private final String myResourceTypeName;
|
||||||
|
private final String myUseSystem;
|
||||||
|
|
||||||
|
public TokenExtractor(String theResourceTypeName, String theUseSystem) {
|
||||||
|
myResourceTypeName = theResourceTypeName;
|
||||||
|
myUseSystem = theUseSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void extract(SearchParamSet<BaseResourceIndexedSearchParam> params, RuntimeSearchParam searchParam, IBase value, String path) {
|
||||||
|
|
||||||
|
// DSTU3+
|
||||||
|
if (value instanceof IBaseEnumeration<?>) {
|
||||||
|
IBaseEnumeration<?> obj = (IBaseEnumeration<?>) value;
|
||||||
|
String system = extractSystem(obj);
|
||||||
|
String code = obj.getValueAsString();
|
||||||
|
BaseSearchParamExtractor.this.createTokenIndexIfNotBlank(myResourceTypeName, params, searchParam, system, code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DSTU2 only
|
||||||
|
if (value instanceof BoundCodeDt) {
|
||||||
|
BoundCodeDt boundCode = (BoundCodeDt) value;
|
||||||
|
Enum valueAsEnum = boundCode.getValueAsEnum();
|
||||||
|
String system = null;
|
||||||
|
if (valueAsEnum != null) {
|
||||||
|
//noinspection unchecked
|
||||||
|
system = boundCode.getBinder().toSystemString(valueAsEnum);
|
||||||
|
}
|
||||||
|
String code = boundCode.getValueAsString();
|
||||||
|
BaseSearchParamExtractor.this.createTokenIndexIfNotBlank(myResourceTypeName, params, searchParam, system, code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof IPrimitiveType) {
|
||||||
|
IPrimitiveType<?> nextValue = (IPrimitiveType<?>) value;
|
||||||
|
String systemAsString = null;
|
||||||
|
String valueAsString = nextValue.getValueAsString();
|
||||||
|
if ("CodeSystem.concept.code".equals(path)) {
|
||||||
|
systemAsString = myUseSystem;
|
||||||
|
} else if ("ValueSet.codeSystem.concept.code".equals(path)) {
|
||||||
|
systemAsString = myUseSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseSearchParamExtractor.this.createTokenIndexIfNotBlank(myResourceTypeName, params, searchParam, systemAsString, valueAsString);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (path) {
|
||||||
|
case "Patient.communication":
|
||||||
|
BaseSearchParamExtractor.this.addToken_PatientCommunication(myResourceTypeName, params, searchParam, value);
|
||||||
|
return;
|
||||||
|
case "Consent.source":
|
||||||
|
// Consent#source-identifier has a path that isn't typed - This is a one-off to deal with that
|
||||||
|
return;
|
||||||
|
case "Location.position":
|
||||||
|
BaseSearchParamExtractor.this.addCoords_Position(myResourceTypeName, params, searchParam, value);
|
||||||
|
return;
|
||||||
|
case "StructureDefinition.context":
|
||||||
|
// TODO: implement this
|
||||||
|
ourLog.warn("StructureDefinition context indexing not currently supported");
|
||||||
|
return;
|
||||||
|
case "CapabilityStatement.rest.security":
|
||||||
|
BaseSearchParamExtractor.this.addToken_CapabilityStatementRestSecurity(myResourceTypeName, params, searchParam, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String nextType = BaseSearchParamExtractor.this.toRootTypeName(value);
|
||||||
|
switch (nextType) {
|
||||||
|
case "Identifier":
|
||||||
|
BaseSearchParamExtractor.this.addToken_Identifier(myResourceTypeName, params, searchParam, value);
|
||||||
|
break;
|
||||||
|
case "CodeableConcept":
|
||||||
|
BaseSearchParamExtractor.this.addToken_CodeableConcept(myResourceTypeName, params, searchParam, value);
|
||||||
|
break;
|
||||||
|
case "Coding":
|
||||||
|
BaseSearchParamExtractor.this.addToken_Coding(myResourceTypeName, params, searchParam, value);
|
||||||
|
break;
|
||||||
|
case "ContactPoint":
|
||||||
|
BaseSearchParamExtractor.this.addToken_ContactPoint(myResourceTypeName, params, searchParam, value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BaseSearchParamExtractor.this.addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void addIgnoredType(FhirContext theCtx, String theType, Set<String> theIgnoredTypes) {
|
private static void addIgnoredType(FhirContext theCtx, String theType, Set<String> theIgnoredTypes) {
|
||||||
BaseRuntimeElementDefinition<?> elementDefinition = theCtx.getElementDefinition(theType);
|
BaseRuntimeElementDefinition<?> elementDefinition = theCtx.getElementDefinition(theType);
|
||||||
if (elementDefinition != null) {
|
if (elementDefinition != null) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.searchparam.extractor;
|
package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.model.entity.*;
|
import ca.uhn.fhir.jpa.model.entity.*;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
@ -42,6 +43,8 @@ public interface ISearchParamExtractor {
|
||||||
|
|
||||||
SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource);
|
SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource);
|
||||||
|
|
||||||
|
SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource, RuntimeSearchParam theSearchParam);
|
||||||
|
|
||||||
SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamSpecial(IBaseResource theResource);
|
SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamSpecial(IBaseResource theResource);
|
||||||
|
|
||||||
SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource);
|
SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource);
|
||||||
|
|
Loading…
Reference in New Issue