Search Parameter Infrastructure Cleanup (#2522)

* Search param service cleanup

* Work on collapsing search param

* Search param cleanup

* Work on build

* Test fix

* Test fixes

* Ongoing work

* Test fix

* Compile fix

* Test fixes

* Test fix

* Test fix

* License header updates

* Remove fixme

* Cleanup

* Cleanup
This commit is contained in:
James Agnew 2021-04-05 17:40:10 -04:00 committed by GitHub
parent 0bf746f23b
commit b617c7690d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
133 changed files with 1008 additions and 974 deletions

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -394,41 +394,30 @@ class ModelScanner {
b.append(" provides compartment membership but is not of type 'reference'"); b.append(" provides compartment membership but is not of type 'reference'");
ourLog.warn(b.toString()); ourLog.warn(b.toString());
continue; continue;
// throw new ConfigurationException(b.toString());
} }
providesMembershipInCompartments.add(next.name()); providesMembershipInCompartments.add(next.name());
} }
List<RuntimeSearchParam.Component> components = null;
if (paramType == RestSearchParameterTypeEnum.COMPOSITE) { if (paramType == RestSearchParameterTypeEnum.COMPOSITE) {
compositeFields.put(nextField, searchParam); components = new ArrayList<>();
continue; for (String next : searchParam.compositeOf()) {
String ref = "http://hl7.org/fhir/SearchParameter/" + theResourceDef.getName().toLowerCase() + "-" + next;
components.add(new RuntimeSearchParam.Component(null, ref));
}
} }
Collection<String> base = Collections.singletonList(theResourceDef.getName()); Collection<String> base = Collections.singletonList(theResourceDef.getName());
RuntimeSearchParam param = new RuntimeSearchParam(null, null, searchParam.name(), searchParam.description(), searchParam.path(), paramType, null, providesMembershipInCompartments, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE, base); String url = null;
if (theResourceDef.isStandardType()) {
url = "http://hl7.org/fhir/SearchParameter/" + theResourceDef.getName().toLowerCase() + "-" + searchParam.name();
}
RuntimeSearchParam param = new RuntimeSearchParam(null, url, searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE, false, components, base);
theResourceDef.addSearchParam(param); theResourceDef.addSearchParam(param);
nameToParam.put(param.getName(), param); nameToParam.put(param.getName(), param);
} }
} }
for (Entry<Field, SearchParamDefinition> nextEntry : compositeFields.entrySet()) {
SearchParamDefinition searchParam = nextEntry.getValue();
List<RuntimeSearchParam> compositeOf = new ArrayList<>();
for (String nextName : searchParam.compositeOf()) {
RuntimeSearchParam param = nameToParam.get(nextName);
if (param == null) {
ourLog.warn("Search parameter {}.{} declares that it is a composite with compositeOf value '{}' but that is not a valid parameter name itself. Valid values are: {}",
theResourceDef.getName(), searchParam.name(), nextName, nameToParam.keySet());
continue;
}
compositeOf.add(param);
}
RuntimeSearchParam param = new RuntimeSearchParam(null, null, searchParam.name(), searchParam.description(), searchParam.path(), RestSearchParameterTypeEnum.COMPOSITE, compositeOf, null, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE);
theResourceDef.addSearchParam(param);
}
} }
private Set<String> toTargetList(Class<? extends IBaseResource>[] theTarget) { private Set<String> toTargetList(Class<? extends IBaseResource>[] theTarget) {

View File

@ -46,7 +46,6 @@ import static org.apache.commons.lang3.StringUtils.trim;
public class RuntimeSearchParam { public class RuntimeSearchParam {
private final IIdType myId; private final IIdType myId;
private final Set<String> myBase; private final Set<String> myBase;
private final List<RuntimeSearchParam> myCompositeOf;
private final String myDescription; private final String myDescription;
private final String myName; private final String myName;
private final RestSearchParameterTypeEnum myParamType; private final RestSearchParameterTypeEnum myParamType;
@ -56,21 +55,29 @@ public class RuntimeSearchParam {
private final RuntimeSearchParamStatusEnum myStatus; private final RuntimeSearchParamStatusEnum myStatus;
private final String myUri; private final String myUri;
private final Map<String, List<IBaseExtension<?, ?>>> myExtensions = new HashMap<>(); private final Map<String, List<IBaseExtension<?, ?>>> myExtensions = new HashMap<>();
private final boolean myUnique;
private final List<Component> myComponents;
private IPhoneticEncoder myPhoneticEncoder; private IPhoneticEncoder myPhoneticEncoder;
/** /**
* Constructor * Constructor
*/ */
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf, public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType,
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) { Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, Collection<String> theBase) {
this(theId, theUri, theName, theDescription, thePath, theParamType, theCompositeOf, theProvidesMembershipInCompartments, theTargets, theStatus, null); this(theId, theUri, theName, theDescription, thePath, theParamType, theProvidesMembershipInCompartments, theTargets, theStatus, false, Collections.emptyList(), theBase);
}
/**
* Copy constructor
*/
public RuntimeSearchParam(RuntimeSearchParam theSp) {
this(theSp.getId(), theSp.getUri(), theSp.getName(), theSp.getDescription(), theSp.getPath(), theSp.getParamType(), theSp.getProvidesMembershipInCompartments(), theSp.getTargets(), theSp.getStatus(), theSp.isUnique(), theSp.getComponents(), theSp.getBase());
} }
/** /**
* Constructor * Constructor
*/ */
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf, public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, boolean theUnique, List<Component> theComponents, Collection<String> theBase) {
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, Collection<String> theBase) {
super(); super();
myId = theId; myId = theId;
@ -79,7 +86,6 @@ public class RuntimeSearchParam {
myDescription = theDescription; myDescription = theDescription;
myPath = thePath; myPath = thePath;
myParamType = theParamType; myParamType = theParamType;
myCompositeOf = theCompositeOf;
myStatus = theStatus; myStatus = theStatus;
if (theProvidesMembershipInCompartments != null && !theProvidesMembershipInCompartments.isEmpty()) { if (theProvidesMembershipInCompartments != null && !theProvidesMembershipInCompartments.isEmpty()) {
myProvidesMembershipInCompartments = Collections.unmodifiableSet(theProvidesMembershipInCompartments); myProvidesMembershipInCompartments = Collections.unmodifiableSet(theProvidesMembershipInCompartments);
@ -104,20 +110,20 @@ public class RuntimeSearchParam {
} else { } else {
myBase = Collections.unmodifiableSet(new HashSet<>(theBase)); myBase = Collections.unmodifiableSet(new HashSet<>(theBase));
} }
myUnique = theUnique;
if (theComponents != null) {
myComponents = Collections.unmodifiableList(theComponents);
} else {
myComponents = Collections.emptyList();
}
} }
/** public List<Component> getComponents() {
* Constructor return myComponents;
*/
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
this(null, null, theName, theDescription, thePath, theParamType, null, theProvidesMembershipInCompartments, theTargets, theStatus);
} }
/** public boolean isUnique() {
* Copy constructor return myUnique;
*/
public RuntimeSearchParam(RuntimeSearchParam theSp) {
this(theSp.getId(), theSp.getUri(), theSp.getName(), theSp.getDescription(), theSp.getPath(), theSp.getParamType(), theSp.getCompositeOf(), theSp.getProvidesMembershipInCompartments(), theSp.getTargets(), theSp.getStatus(), theSp.getBase());
} }
/** /**
@ -205,10 +211,6 @@ public class RuntimeSearchParam {
return myStatus; return myStatus;
} }
public List<RuntimeSearchParam> getCompositeOf() {
return myCompositeOf;
}
public String getDescription() { public String getDescription() {
return myDescription; return myDescription;
} }
@ -247,13 +249,6 @@ public class RuntimeSearchParam {
return myProvidesMembershipInCompartments; return myProvidesMembershipInCompartments;
} }
public enum RuntimeSearchParamStatusEnum {
ACTIVE,
DRAFT,
RETIRED,
UNKNOWN
}
public RuntimeSearchParam setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) { public RuntimeSearchParam setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {
myPhoneticEncoder = thePhoneticEncoder; myPhoneticEncoder = thePhoneticEncoder;
return this; return this;
@ -265,4 +260,42 @@ public class RuntimeSearchParam {
} }
return myPhoneticEncoder.encode(theString); return myPhoneticEncoder.encode(theString);
} }
public enum RuntimeSearchParamStatusEnum {
ACTIVE,
DRAFT,
RETIRED,
UNKNOWN
}
public static class Component {
private final String myExpression;
private final String myReference;
/**
* Constructor
*/
public Component(String theExpression, String theReference) {
myExpression = theExpression;
myReference = theReference;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("expression", myExpression)
.append("reference", myReference)
.toString();
}
public String getExpression() {
return myExpression;
}
public String getReference() {
return myReference;
}
}
} }

View File

@ -1,5 +1,19 @@
package ca.uhn.fhir.rest.param; package ca.uhn.fhir.rest.param;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
@ -8,25 +22,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.binder.QueryParameterAndBinder;
import ca.uhn.fhir.util.ReflectionUtil;
import ca.uhn.fhir.util.UrlUtil;
/* /*
* #%L * #%L
* HAPI FHIR - Core Library * HAPI FHIR - Core Library
@ -59,126 +54,6 @@ public class ParameterUtil {
return (T) value; return (T) value;
} }
/**
* This is a utility method intended provided to help the JPA module.
*/
public static IQueryParameterAnd<?> parseQueryParams(FhirContext theContext, RestSearchParameterTypeEnum paramType,
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
QueryParameterAndBinder binder;
switch (paramType) {
case COMPOSITE:
throw new UnsupportedOperationException();
case DATE:
binder = new QueryParameterAndBinder(DateAndListParam.class,
Collections.emptyList());
break;
case NUMBER:
binder = new QueryParameterAndBinder(NumberAndListParam.class,
Collections.emptyList());
break;
case QUANTITY:
binder = new QueryParameterAndBinder(QuantityAndListParam.class,
Collections.emptyList());
break;
case REFERENCE:
binder = new QueryParameterAndBinder(ReferenceAndListParam.class,
Collections.emptyList());
break;
case STRING:
binder = new QueryParameterAndBinder(StringAndListParam.class,
Collections.emptyList());
break;
case TOKEN:
binder = new QueryParameterAndBinder(TokenAndListParam.class,
Collections.emptyList());
break;
case URI:
binder = new QueryParameterAndBinder(UriAndListParam.class,
Collections.emptyList());
break;
case HAS:
binder = new QueryParameterAndBinder(HasAndListParam.class,
Collections.emptyList());
break;
case SPECIAL:
binder = new QueryParameterAndBinder(SpecialAndListParam.class,
Collections.emptyList());
break;
default:
throw new IllegalArgumentException("Parameter '" + theUnqualifiedParamName + "' has type " + paramType + " which is currently not supported.");
}
return binder.parse(theContext, theUnqualifiedParamName, theParameters);
}
/**
* This is a utility method intended provided to help the JPA module.
*/
public static IQueryParameterAnd<?> parseQueryParams(FhirContext theContext, RuntimeSearchParam theParamDef,
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
RestSearchParameterTypeEnum paramType = theParamDef.getParamType();
if (paramType == RestSearchParameterTypeEnum.COMPOSITE) {
List<RuntimeSearchParam> theCompositList = theParamDef.getCompositeOf();
if (theCompositList == null) {
throw new ConfigurationException("Search parameter of type " + theUnqualifiedParamName
+ " can be found in parameter annotation, found ");
}
if (theCompositList.size() != 2) {
throw new ConfigurationException("Search parameter of type " + theUnqualifiedParamName
+ " must have 2 composite types declared in parameter annotation, found "
+ theCompositList.size());
}
RuntimeSearchParam left = theCompositList.get(0);
RuntimeSearchParam right = theCompositList.get(1);
@SuppressWarnings({ "unchecked", "rawtypes" })
CompositeAndListParam<IQueryParameterType, IQueryParameterType> cp = new CompositeAndListParam(
getCompositBindingClass(left.getParamType(), left.getName()),
getCompositBindingClass(right.getParamType(), right.getName()));
cp.setValuesAsQueryTokens(theContext, theUnqualifiedParamName, theParameters);
return cp;
} else {
return parseQueryParams(theContext, paramType, theUnqualifiedParamName, theParameters);
}
}
private static Class<?> getCompositBindingClass(RestSearchParameterTypeEnum paramType,
String theUnqualifiedParamName) {
switch (paramType) {
case DATE:
return DateParam.class;
case NUMBER:
return NumberParam.class;
case QUANTITY:
return QuantityParam.class;
case REFERENCE:
return ReferenceParam.class;
case STRING:
return StringParam.class;
case TOKEN:
return TokenParam.class;
case URI:
return UriParam.class;
case HAS:
return HasParam.class;
case SPECIAL:
return SpecialParam.class;
default:
throw new IllegalArgumentException("Parameter '" + theUnqualifiedParamName + "' has type " + paramType
+ " which is currently not supported.");
}
}
/** /**
* Removes :modifiers and .chains from URL parameter names * Removes :modifiers and .chains from URL parameter names
*/ */

View File

@ -3,14 +3,14 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-bom</artifactId> <artifactId>hapi-fhir-bom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>HAPI FHIR BOM</name> <name>HAPI FHIR BOM</name>
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId> <artifactId>hapi-fhir-cli</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom</relativePath> <relativePath>../../hapi-deployable-pom</relativePath>
</parent> </parent>

View File

@ -37,7 +37,7 @@ import ca.uhn.fhir.jpa.provider.dstu3.JpaConformanceProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.JpaCapabilityStatementProvider; import ca.uhn.fhir.jpa.provider.JpaCapabilityStatementProvider;
import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt;
import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
@ -78,13 +78,13 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId> <artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-subscription</artifactId> <artifactId>hapi-fhir-jpaserver-subscription</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -101,7 +101,7 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-testpage-overlay</artifactId> <artifactId>hapi-fhir-testpage-overlay</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<classifier>classes</classifier> <classifier>classes</classifier>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -11,7 +11,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.dao;
*/ */
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
@ -34,7 +33,8 @@ import ca.uhn.fhir.jpa.model.cross.IBasePersistedResource;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster; import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.model.api.IQueryParameterAnd; import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.rest.api.QualifiedParamList; import ca.uhn.fhir.rest.api.QualifiedParamList;
@ -44,7 +44,6 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.SimplePreResourceAccessDetails; import ca.uhn.fhir.rest.api.server.SimplePreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails; import ca.uhn.fhir.rest.api.server.SimplePreResourceShowDetails;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.param.QualifierDetails; import ca.uhn.fhir.rest.param.QualifierDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
@ -339,13 +338,12 @@ public abstract class BaseStorageDao {
} }
// Should not be null since the check above would have caught it // Should not be null since the check above would have caught it
RuntimeResourceDefinition resourceDef = getContext().getResourceDefinition(getResourceName()); RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(getResourceName(), qualifiedParamName.getParamName());
RuntimeSearchParam paramDef = mySearchParamRegistry.getSearchParamByName(resourceDef, qualifiedParamName.getParamName());
for (String nextValue : theSource.get(nextParamName)) { for (String nextValue : theSource.get(nextParamName)) {
QualifiedParamList qualifiedParam = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifiedParamName.getWholeQualifier(), nextValue); QualifiedParamList qualifiedParam = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifiedParamName.getWholeQualifier(), nextValue);
List<QualifiedParamList> paramList = Collections.singletonList(qualifiedParam); List<QualifiedParamList> paramList = Collections.singletonList(qualifiedParam);
IQueryParameterAnd<?> parsedParam = ParameterUtil.parseQueryParams(getContext(), paramDef, nextParamName, paramList); IQueryParameterAnd<?> parsedParam = JpaParamUtil.parseQueryParams(mySearchParamRegistry, getContext(), paramDef, nextParamName, paramList);
theTarget.add(qualifiedParamName.getParamName(), parsedParam); theTarget.add(qualifiedParamName.getParamName(), parsedParam);
} }

View File

@ -42,7 +42,6 @@ import ca.uhn.fhir.jpa.entity.ResourceSearchView;
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails; import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam; import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceLink; import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
@ -51,9 +50,8 @@ import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.lastn.IElasticsearchSvc; import ca.uhn.fhir.jpa.search.lastn.IElasticsearchSvc;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.Dstu3DistanceHelper; import ca.uhn.fhir.jpa.searchparam.util.Dstu3DistanceHelper;
import ca.uhn.fhir.jpa.searchparam.util.LastNParameterHelper; import ca.uhn.fhir.jpa.searchparam.util.LastNParameterHelper;
import ca.uhn.fhir.jpa.util.BaseIterator; import ca.uhn.fhir.jpa.util.BaseIterator;
@ -483,8 +481,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
return orders; return orders;
} }
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceName); RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(myResourceName, theSort.getParamName());
RuntimeSearchParam param = mySearchParamRegistry.getSearchParamByName(resourceDef, theSort.getParamName());
if (param == null) { if (param == null) {
throw new InvalidRequestException("Unknown sort parameter '" + theSort.getParamName() + "'"); throw new InvalidRequestException("Unknown sort parameter '" + theSort.getParamName() + "'");
} }
@ -757,7 +754,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
String paramName = nextInclude.getParamName(); String paramName = nextInclude.getParamName();
if (isNotBlank(paramName)) { if (isNotBlank(paramName)) {
param = mySearchParamRegistry.getSearchParamByName(def, paramName); param = mySearchParamRegistry.getActiveSearchParam(resType, paramName);
} else { } else {
param = null; param = null;
} }
@ -876,7 +873,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
// Since we're going to remove elements below // Since we're going to remove elements below
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList)); theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
List<JpaRuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet()); List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
if (activeUniqueSearchParams.size() > 0) { if (activeUniqueSearchParams.size() > 0) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -25,26 +25,26 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.model.RequestPartitionId; import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.MatchResourceUrlService; import ca.uhn.fhir.jpa.dao.MatchResourceUrlService;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao; import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam; import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceLink; import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService; import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -148,13 +148,14 @@ public class SearchParamWithInlineReferencesExtractor {
private void extractCompositeStringUniques(ResourceTable theEntity, ResourceIndexedSearchParams theParams) { private void extractCompositeStringUniques(ResourceTable theEntity, ResourceIndexedSearchParams theParams) {
final String resourceType = theEntity.getResourceType(); final String resourceType = theEntity.getResourceType();
List<JpaRuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType); List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType);
for (JpaRuntimeSearchParam next : uniqueSearchParams) { for (RuntimeSearchParam next : uniqueSearchParams) {
List<List<String>> partsChoices = new ArrayList<>(); List<List<String>> partsChoices = new ArrayList<>();
for (RuntimeSearchParam nextCompositeOf : next.getCompositeOf()) { List<RuntimeSearchParam> compositeComponents = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, next);
for (RuntimeSearchParam nextCompositeOf : compositeComponents) {
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null; Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
Collection<ResourceLink> linksForCompositePart = null; Collection<ResourceLink> linksForCompositePart = null;
Collection<String> linksForCompositePartWantPaths = null; Collection<String> linksForCompositePartWantPaths = null;

View File

@ -47,7 +47,8 @@ import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams; import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam; import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster; import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.model.api.IQueryParameterAnd; import ca.uhn.fhir.model.api.IQueryParameterAnd;
@ -64,7 +65,6 @@ import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.HasParam; import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.NumberParam; import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.param.QuantityParam; import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.SpecialParam; import ca.uhn.fhir.rest.param.SpecialParam;
@ -315,9 +315,9 @@ class PredicateBuilderReference extends BasePredicateBuilder {
boolean isMeta = ResourceMetaParams.RESOURCE_META_PARAMS.containsKey(chain); boolean isMeta = ResourceMetaParams.RESOURCE_META_PARAMS.containsKey(chain);
RuntimeSearchParam param = null; RuntimeSearchParam param = null;
if (!isMeta) { if (!isMeta) {
param = mySearchParamRegistry.getSearchParamByName(typeDef, chain); param = mySearchParamRegistry.getActiveSearchParam(subResourceName, chain);
if (param == null) { if (param == null) {
ourLog.debug("Type {} doesn't have search param {}", nextType.getSimpleName(), param); ourLog.debug("Type {} doesn't have search param {}", subResourceName, param);
continue; continue;
} }
} }
@ -397,8 +397,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
} }
if (resourceTypes.isEmpty()) { if (resourceTypes.isEmpty()) {
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(theResourceName); RuntimeSearchParam searchParamByName = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
RuntimeSearchParam searchParamByName = mySearchParamRegistry.getSearchParamByName(resourceDef, theParamName);
if (searchParamByName == null) { if (searchParamByName == null) {
throw new InternalErrorException("Could not find parameter " + theParamName); throw new InternalErrorException("Could not find parameter " + theParamName);
} }
@ -480,8 +479,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
} }
Predicate createResourceLinkPathPredicate(String theResourceName, String theParamName, From<?, ? extends ResourceLink> from) { Predicate createResourceLinkPathPredicate(String theResourceName, String theParamName, From<?, ? extends ResourceLink> from) {
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(theResourceName); RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
RuntimeSearchParam param = mySearchParamRegistry.getSearchParamByName(resourceDef, theParamName);
List<String> path = param.getPathsSplit(); List<String> path = param.getPathsSplit();
/* /*
@ -798,7 +796,7 @@ class PredicateBuilderReference extends BasePredicateBuilder {
qp = new TokenParam(); qp = new TokenParam();
break; break;
case COMPOSITE: case COMPOSITE:
List<RuntimeSearchParam> compositeOf = theParam.getCompositeOf(); List<RuntimeSearchParam> compositeOf = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, theParam);
if (compositeOf.size() != 2) { if (compositeOf.size() != 2) {
throw new InternalErrorException("Parameter " + theParam.getName() + " has " + compositeOf.size() + " composite parts. Don't know how handlt this."); throw new InternalErrorException("Parameter " + theParam.getName() + " has " + compositeOf.size() + " composite parts. Don't know how handlt this.");
} }
@ -957,20 +955,19 @@ class PredicateBuilderReference extends BasePredicateBuilder {
//Ensure that the name of the search param //Ensure that the name of the search param
// (e.g. the `code` in Patient?_has:Observation:subject:code=sys|val) // (e.g. the `code` in Patient?_has:Observation:subject:code=sys|val)
// exists on the target resource type. // exists on the target resource type.
RuntimeSearchParam owningParameterDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramName); RuntimeSearchParam owningParameterDef = mySearchParamRegistry.getActiveSearchParam(targetResourceType, paramName);
if (owningParameterDef == null) { if (owningParameterDef == null) {
throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + parameterName); throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + parameterName);
} }
//Ensure that the name of the back-referenced search param on the target (e.g. the `subject` in Patient?_has:Observation:subject:code=sys|val) //Ensure that the name of the back-referenced search param on the target (e.g. the `subject` in Patient?_has:Observation:subject:code=sys|val)
//exists on the target resource. //exists on the target resource.
owningParameterDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramReference); RuntimeSearchParam joiningParameterDef = mySearchParamRegistry.getActiveSearchParam(targetResourceType, paramReference);
if (owningParameterDef == null) { if (joiningParameterDef == null) {
throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + paramReference); throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + paramReference);
} }
RuntimeSearchParam paramDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramName); IQueryParameterAnd<IQueryParameterOr<IQueryParameterType>> parsedParam = (IQueryParameterAnd<IQueryParameterOr<IQueryParameterType>>) JpaParamUtil.parseQueryParams(mySearchParamRegistry, myContext, owningParameterDef, paramName, parameters);
IQueryParameterAnd<IQueryParameterOr<IQueryParameterType>> parsedParam = (IQueryParameterAnd<IQueryParameterOr<IQueryParameterType>>) ParameterUtil.parseQueryParams(myContext, paramDef, paramName, parameters);
for (IQueryParameterOr<IQueryParameterType> next : parsedParam.getValuesAsQueryTokens()) { for (IQueryParameterOr<IQueryParameterType> next : parsedParam.getValuesAsQueryTokens()) {
orValues.addAll(next.getValuesAsQueryTokens()); orValues.addAll(next.getValuesAsQueryTokens());
@ -1011,11 +1008,12 @@ class PredicateBuilderReference extends BasePredicateBuilder {
} }
CompositeParam<?, ?> cp = (CompositeParam<?, ?>) or; CompositeParam<?, ?> cp = (CompositeParam<?, ?>) or;
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0); List<RuntimeSearchParam> componentParams = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, theParamDef);
RuntimeSearchParam left = componentParams.get(0);
IQueryParameterType leftValue = cp.getLeftValue(); IQueryParameterType leftValue = cp.getLeftValue();
myQueryStack.addPredicate(createCompositeParamPart(theResourceName, myQueryStack.getRootForComposite(), left, leftValue, theRequestPartitionId)); myQueryStack.addPredicate(createCompositeParamPart(theResourceName, myQueryStack.getRootForComposite(), left, leftValue, theRequestPartitionId));
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1); RuntimeSearchParam right = componentParams.get(1);
IQueryParameterType rightValue = cp.getRightValue(); IQueryParameterType rightValue = cp.getRightValue();
myQueryStack.addPredicate(createCompositeParamPart(theResourceName, myQueryStack.getRootForComposite(), right, rightValue, theRequestPartitionId)); myQueryStack.addPredicate(createCompositeParamPart(theResourceName, myQueryStack.getRootForComposite(), right, rightValue, theRequestPartitionId));

View File

@ -8,21 +8,18 @@ import ca.uhn.fhir.jpa.api.dao.IFhirResourceDaoSearchParameter;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao; import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor; import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.HapiExtensions; import ca.uhn.fhir.util.HapiExtensions;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.SearchParameter; import org.hl7.fhir.r4.model.SearchParameter;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;

View File

@ -36,7 +36,8 @@ import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionEntity;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.partition.SystemRequestDetails; import ca.uhn.fhir.jpa.partition.SystemRequestDetails;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistryController;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParam;
@ -106,6 +107,8 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc {
@Autowired @Autowired
private ISearchParamRegistry mySearchParamRegistry; private ISearchParamRegistry mySearchParamRegistry;
@Autowired @Autowired
private ISearchParamRegistryController mySearchParamRegistryController;
@Autowired
private PartitionSettings myPartitionSettings; private PartitionSettings myPartitionSettings;
/** /**
* Constructor * Constructor
@ -175,7 +178,7 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc {
install(npmPackage, theInstallationSpec, retVal); install(npmPackage, theInstallationSpec, retVal);
// If any SearchParameters were installed, let's load them right away // If any SearchParameters were installed, let's load them right away
mySearchParamRegistry.refreshCacheIfNecessary(); mySearchParamRegistryController.refreshCacheIfNecessary();
} }
} catch (IOException e) { } catch (IOException e) {

View File

@ -27,7 +27,7 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.provider.ServerCapabilityStatementProvider; import ca.uhn.fhir.rest.server.provider.ServerCapabilityStatementProvider;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.ExtensionConstants; import ca.uhn.fhir.util.ExtensionConstants;
import ca.uhn.fhir.util.ExtensionUtil; import ca.uhn.fhir.util.ExtensionUtil;
@ -59,7 +59,7 @@ public class JpaCapabilityStatementProvider extends ServerCapabilityStatementPro
/** /**
* Constructor * Constructor
*/ */
public JpaCapabilityStatementProvider(@Nonnull RestfulServer theRestfulServer, @Nonnull IFhirSystemDao<?, ?> theSystemDao, @Nonnull DaoConfig theDaoConfig, @Nonnull ISearchParamRetriever theSearchParamRegistry, IValidationSupport theValidationSupport) { public JpaCapabilityStatementProvider(@Nonnull RestfulServer theRestfulServer, @Nonnull IFhirSystemDao<?, ?> theSystemDao, @Nonnull DaoConfig theDaoConfig, @Nonnull ISearchParamRegistry theSearchParamRegistry, IValidationSupport theValidationSupport) {
super(theRestfulServer, theSearchParamRegistry, theValidationSupport); super(theRestfulServer, theSearchParamRegistry, theValidationSupport);
Validate.notNull(theRestfulServer); Validate.notNull(theRestfulServer);

View File

@ -26,7 +26,7 @@ import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
import ca.uhn.fhir.util.ExtensionConstants; import ca.uhn.fhir.util.ExtensionConstants;
import org.hl7.fhir.dstu3.model.Bundle; import org.hl7.fhir.dstu3.model.Bundle;
@ -53,7 +53,7 @@ public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.se
private volatile CapabilityStatement myCachedValue; private volatile CapabilityStatement myCachedValue;
private DaoConfig myDaoConfig; private DaoConfig myDaoConfig;
private ISearchParamRetriever mySearchParamRegistry; private ISearchParamRegistry mySearchParamRegistry;
private String myImplementationDescription; private String myImplementationDescription;
private boolean myIncludeResourceCounts; private boolean myIncludeResourceCounts;
private RestfulServer myRestfulServer; private RestfulServer myRestfulServer;
@ -72,7 +72,7 @@ public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.se
/** /**
* Constructor * Constructor
*/ */
public JpaConformanceProviderDstu3(RestfulServer theRestfulServer, IFhirSystemDao<Bundle, Meta> theSystemDao, DaoConfig theDaoConfig, ISearchParamRetriever theSearchParamRegistry) { public JpaConformanceProviderDstu3(RestfulServer theRestfulServer, IFhirSystemDao<Bundle, Meta> theSystemDao, DaoConfig theDaoConfig, ISearchParamRegistry theSearchParamRegistry) {
super(theRestfulServer); super(theRestfulServer);
myRestfulServer = theRestfulServer; myRestfulServer = theRestfulServer;
mySystemDao = theSystemDao; mySystemDao = theSystemDao;
@ -82,7 +82,7 @@ public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.se
setIncludeResourceCounts(true); setIncludeResourceCounts(true);
} }
public void setSearchParamRegistry(ISearchParamRetriever theSearchParamRegistry) { public void setSearchParamRegistry(ISearchParamRegistry theSearchParamRegistry) {
mySearchParamRegistry = theSearchParamRegistry; mySearchParamRegistry = theSearchParamRegistry;
} }

View File

@ -52,9 +52,8 @@ import ca.uhn.fhir.jpa.search.builder.predicate.TokenPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.predicate.UriPredicateBuilder; import ca.uhn.fhir.jpa.search.builder.predicate.UriPredicateBuilder;
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder; import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.SearchContainedModeEnum;
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor; import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam; import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.model.api.IQueryParameterAnd; import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr; import ca.uhn.fhir.model.api.IQueryParameterOr;
@ -63,13 +62,13 @@ import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.QualifiedParamList; import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.api.SearchContainedModeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.CompositeParam; import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.HasParam; import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.NumberParam; import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.rest.param.ParameterUtil;
import ca.uhn.fhir.rest.param.QuantityParam; import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.StringParam;
@ -80,6 +79,7 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.healthmarketscience.sqlbuilder.BinaryCondition; import com.healthmarketscience.sqlbuilder.BinaryCondition;
import com.healthmarketscience.sqlbuilder.ComboCondition; import com.healthmarketscience.sqlbuilder.ComboCondition;
@ -298,11 +298,12 @@ public class QueryStack {
} }
CompositeParam<?, ?> cp = (CompositeParam<?, ?>) next; CompositeParam<?, ?> cp = (CompositeParam<?, ?>) next;
RuntimeSearchParam left = theParamDef.getCompositeOf().get(0); List<RuntimeSearchParam> componentParams = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, theParamDef);
RuntimeSearchParam left = componentParams.get(0);
IQueryParameterType leftValue = cp.getLeftValue(); IQueryParameterType leftValue = cp.getLeftValue();
Condition leftPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, theSpnamePrefix, left, leftValue, theRequestPartitionId); Condition leftPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, theSpnamePrefix, left, leftValue, theRequestPartitionId);
RuntimeSearchParam right = theParamDef.getCompositeOf().get(1); RuntimeSearchParam right = componentParams.get(1);
IQueryParameterType rightValue = cp.getRightValue(); IQueryParameterType rightValue = cp.getRightValue();
Condition rightPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, theSpnamePrefix, right, rightValue, theRequestPartitionId); Condition rightPredicate = createPredicateCompositePart(theSourceJoinColumn, theResourceName, theSpnamePrefix, right, rightValue, theRequestPartitionId);
@ -333,9 +334,16 @@ public class QueryStack {
case QUANTITY: { case QUANTITY: {
return createPredicateQuantity(theSourceJoinColumn, theResourceName, theSpnamePrefix, theParam, Collections.singletonList(theParamValue), null, theRequestPartitionId); return createPredicateQuantity(theSourceJoinColumn, theResourceName, theSpnamePrefix, theParam, Collections.singletonList(theParamValue), null, theRequestPartitionId);
} }
case NUMBER:
case REFERENCE:
case COMPOSITE:
case URI:
case HAS:
case SPECIAL:
default:
throw new InvalidRequestException("Don't know how to handle composite parameter with type of " + theParam.getParamType());
} }
throw new InvalidRequestException("Don't know how to handle composite parameter with type of " + theParam.getParamType());
} }
public Condition createPredicateCoords(@Nullable DbColumn theSourceJoinColumn, public Condition createPredicateCoords(@Nullable DbColumn theSourceJoinColumn,
@ -360,11 +368,11 @@ public class QueryStack {
} }
public Condition createPredicateDate(@Nullable DbColumn theSourceJoinColumn, String theResourceName, public Condition createPredicateDate(@Nullable DbColumn theSourceJoinColumn, String theResourceName,
String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList, String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) { SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName()); String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName());
PredicateBuilderCacheLookupResult<DatePredicateBuilder> predicateBuilderLookupResult = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.DATE, theSourceJoinColumn, paramName, () -> mySqlBuilder.addDatePredicateBuilder(theSourceJoinColumn)); PredicateBuilderCacheLookupResult<DatePredicateBuilder> predicateBuilderLookupResult = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.DATE, theSourceJoinColumn, paramName, () -> mySqlBuilder.addDatePredicateBuilder(theSourceJoinColumn));
DatePredicateBuilder predicateBuilder = predicateBuilderLookupResult.getResult(); DatePredicateBuilder predicateBuilder = predicateBuilderLookupResult.getResult();
boolean cacheHit = predicateBuilderLookupResult.isCacheHit(); boolean cacheHit = predicateBuilderLookupResult.isCacheHit();
@ -420,51 +428,56 @@ public class QueryStack {
String paramName = theFilter.getParamPath().getName(); String paramName = theFilter.getParamPath().getName();
if (paramName.equals(IAnyResource.SP_RES_ID)) { switch (paramName) {
TokenParam param = new TokenParam(); case IAnyResource.SP_RES_ID: {
param.setValueAsQueryToken(null, null, null, theFilter.getValue());
return theQueryStack3.createPredicateResourceId(null, Collections.singletonList(Collections.singletonList(param)), theResourceName, theFilter.getOperation(), theRequestPartitionId);
} else if (paramName.equals(IAnyResource.SP_RES_LANGUAGE)) {
return theQueryStack3.createPredicateLanguage(Collections.singletonList(Collections.singletonList(new StringParam(theFilter.getValue()))), theFilter.getOperation());
} else if (paramName.equals(Constants.PARAM_SOURCE)) {
TokenParam param = new TokenParam();
param.setValueAsQueryToken(null, null, null, theFilter.getValue());
return createPredicateSource(null, Collections.singletonList(param));
} else {
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramName);
if (searchParam == null) {
Collection<String> validNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName);
String msg = myFhirContext.getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "invalidSearchParameter", paramName, theResourceName, validNames);
throw new InvalidRequestException(msg);
}
RestSearchParameterTypeEnum typeEnum = searchParam.getParamType();
if (typeEnum == RestSearchParameterTypeEnum.URI) {
return theQueryStack3.createPredicateUri(null, theResourceName, null, searchParam, Collections.singletonList(new UriParam(theFilter.getValue())), theFilter.getOperation(), theRequest, theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.STRING) {
return theQueryStack3.createPredicateString(null, theResourceName, null, searchParam, Collections.singletonList(new StringParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.DATE) {
return theQueryStack3.createPredicateDate(null, theResourceName, null, searchParam, Collections.singletonList(new DateParam(fromOperation(theFilter.getOperation()), theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.NUMBER) {
return theQueryStack3.createPredicateNumber(null, theResourceName, null, searchParam, Collections.singletonList(new NumberParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.REFERENCE) {
SearchFilterParser.CompareOperation operation = theFilter.getOperation();
String resourceType = null; // The value can either have (Patient/123) or not have (123) a resource type, either way it's not needed here
String chain = (theFilter.getParamPath().getNext() != null) ? theFilter.getParamPath().getNext().toString() : null;
String value = theFilter.getValue();
ReferenceParam referenceParam = new ReferenceParam(resourceType, chain, value);
return theQueryStack3.createPredicateReference(null, theResourceName, paramName, Collections.singletonList(referenceParam), operation, theRequest, theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.QUANTITY) {
return theQueryStack3.createPredicateQuantity(null, theResourceName, null, searchParam, Collections.singletonList(new QuantityParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.COMPOSITE) {
throw new InvalidRequestException("Composite search parameters not currently supported with _filter clauses");
} else if (typeEnum == RestSearchParameterTypeEnum.TOKEN) {
TokenParam param = new TokenParam(); TokenParam param = new TokenParam();
param.setValueAsQueryToken(null, param.setValueAsQueryToken(null, null, null, theFilter.getValue());
null, return theQueryStack3.createPredicateResourceId(null, Collections.singletonList(Collections.singletonList(param)), theResourceName, theFilter.getOperation(), theRequestPartitionId);
null,
theFilter.getValue());
return theQueryStack3.createPredicateToken(null, theResourceName, null, searchParam, Collections.singletonList(param), theFilter.getOperation(), theRequestPartitionId);
} }
case IAnyResource.SP_RES_LANGUAGE: {
return theQueryStack3.createPredicateLanguage(Collections.singletonList(Collections.singletonList(new StringParam(theFilter.getValue()))), theFilter.getOperation());
}
case Constants.PARAM_SOURCE: {
TokenParam param = new TokenParam();
param.setValueAsQueryToken(null, null, null, theFilter.getValue());
return createPredicateSource(null, Collections.singletonList(param));
}
default:
RuntimeSearchParam searchParam = mySearchParamRegistry.getActiveSearchParam(theResourceName, paramName);
if (searchParam == null) {
Collection<String> validNames = mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(theResourceName);
String msg = myFhirContext.getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "invalidSearchParameter", paramName, theResourceName, validNames);
throw new InvalidRequestException(msg);
}
RestSearchParameterTypeEnum typeEnum = searchParam.getParamType();
if (typeEnum == RestSearchParameterTypeEnum.URI) {
return theQueryStack3.createPredicateUri(null, theResourceName, null, searchParam, Collections.singletonList(new UriParam(theFilter.getValue())), theFilter.getOperation(), theRequest, theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.STRING) {
return theQueryStack3.createPredicateString(null, theResourceName, null, searchParam, Collections.singletonList(new StringParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.DATE) {
return theQueryStack3.createPredicateDate(null, theResourceName, null, searchParam, Collections.singletonList(new DateParam(fromOperation(theFilter.getOperation()), theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.NUMBER) {
return theQueryStack3.createPredicateNumber(null, theResourceName, null, searchParam, Collections.singletonList(new NumberParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.REFERENCE) {
SearchFilterParser.CompareOperation operation = theFilter.getOperation();
String resourceType = null; // The value can either have (Patient/123) or not have (123) a resource type, either way it's not needed here
String chain = (theFilter.getParamPath().getNext() != null) ? theFilter.getParamPath().getNext().toString() : null;
String value = theFilter.getValue();
ReferenceParam referenceParam = new ReferenceParam(resourceType, chain, value);
return theQueryStack3.createPredicateReference(null, theResourceName, paramName, Collections.singletonList(referenceParam), operation, theRequest, theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.QUANTITY) {
return theQueryStack3.createPredicateQuantity(null, theResourceName, null, searchParam, Collections.singletonList(new QuantityParam(theFilter.getValue())), theFilter.getOperation(), theRequestPartitionId);
} else if (typeEnum == RestSearchParameterTypeEnum.COMPOSITE) {
throw new InvalidRequestException("Composite search parameters not currently supported with _filter clauses");
} else if (typeEnum == RestSearchParameterTypeEnum.TOKEN) {
TokenParam param = new TokenParam();
param.setValueAsQueryToken(null,
null,
null,
theFilter.getValue());
return theQueryStack3.createPredicateToken(null, theResourceName, null, searchParam, Collections.singletonList(param), theFilter.getOperation(), theRequestPartitionId);
}
break;
} }
return null; return null;
} }
@ -493,9 +506,8 @@ public class QueryStack {
continue; continue;
} }
RuntimeResourceDefinition targetResourceDefinition;
try { try {
targetResourceDefinition = myFhirContext.getResourceDefinition(targetResourceType); myFhirContext.getResourceDefinition(targetResourceType);
} catch (DataFormatException e) { } catch (DataFormatException e) {
throw new InvalidRequestException("Invalid resource type: " + targetResourceType); throw new InvalidRequestException("Invalid resource type: " + targetResourceType);
} }
@ -518,20 +530,19 @@ public class QueryStack {
//Ensure that the name of the search param //Ensure that the name of the search param
// (e.g. the `code` in Patient?_has:Observation:subject:code=sys|val) // (e.g. the `code` in Patient?_has:Observation:subject:code=sys|val)
// exists on the target resource type. // exists on the target resource type.
RuntimeSearchParam owningParameterDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramName); RuntimeSearchParam owningParameterDef = mySearchParamRegistry.getActiveSearchParam(targetResourceType, paramName);
if (owningParameterDef == null) { if (owningParameterDef == null) {
throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + parameterName); throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + parameterName);
} }
//Ensure that the name of the back-referenced search param on the target (e.g. the `subject` in Patient?_has:Observation:subject:code=sys|val) //Ensure that the name of the back-referenced search param on the target (e.g. the `subject` in Patient?_has:Observation:subject:code=sys|val)
//exists on the target resource. //exists on the target resource.
owningParameterDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramReference); RuntimeSearchParam joiningParameterDef = mySearchParamRegistry.getActiveSearchParam(targetResourceType, paramReference);
if (owningParameterDef == null) { if (joiningParameterDef == null) {
throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + paramReference); throw new InvalidRequestException("Unknown parameter name: " + targetResourceType + ':' + paramReference);
} }
RuntimeSearchParam paramDef = mySearchParamRegistry.getSearchParamByName(targetResourceDefinition, paramName); IQueryParameterAnd<?> parsedParam = JpaParamUtil.parseQueryParams(mySearchParamRegistry, myFhirContext, owningParameterDef, paramName, parameters);
IQueryParameterAnd<?> parsedParam = ParameterUtil.parseQueryParams(myFhirContext, paramDef, paramName, parameters);
for (IQueryParameterOr<?> next : parsedParam.getValuesAsQueryTokens()) { for (IQueryParameterOr<?> next : parsedParam.getValuesAsQueryTokens()) {
orValues.addAll(next.getValuesAsQueryTokens()); orValues.addAll(next.getValuesAsQueryTokens());
@ -607,8 +618,8 @@ public class QueryStack {
} }
public Condition createPredicateNumber(@Nullable DbColumn theSourceJoinColumn, String theResourceName, public Condition createPredicateNumber(@Nullable DbColumn theSourceJoinColumn, String theResourceName,
String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList, String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) { SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName()); String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName());
@ -634,7 +645,7 @@ public class QueryStack {
operation = toOperation(param.getPrefix()); operation = toOperation(param.getPrefix());
} }
Condition predicate = join.createPredicateNumeric(theResourceName, paramName, operation, value, theRequestPartitionId, nextOr); Condition predicate = join.createPredicateNumeric(theResourceName, paramName, operation, value, theRequestPartitionId, nextOr);
codePredicates.add(predicate); codePredicates.add(predicate);
@ -648,8 +659,8 @@ public class QueryStack {
} }
public Condition createPredicateQuantity(@Nullable DbColumn theSourceJoinColumn, String theResourceName, public Condition createPredicateQuantity(@Nullable DbColumn theSourceJoinColumn, String theResourceName,
String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList, String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) { SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName()); String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName());
@ -719,9 +730,9 @@ public class QueryStack {
} }
private Condition createPredicateReferenceForContainedResource(@Nullable DbColumn theSourceJoinColumn, private Condition createPredicateReferenceForContainedResource(@Nullable DbColumn theSourceJoinColumn,
String theResourceName, String theParamName, RuntimeSearchParam theSearchParam, String theResourceName, String theParamName, RuntimeSearchParam theSearchParam,
List<? extends IQueryParameterType> theList, SearchFilterParser.CompareOperation theOperation, List<? extends IQueryParameterType> theList, SearchFilterParser.CompareOperation theOperation,
RequestDetails theRequest, RequestPartitionId theRequestPartitionId) { RequestDetails theRequest, RequestPartitionId theRequestPartitionId) {
String spnamePrefix = theParamName; String spnamePrefix = theParamName;
@ -767,7 +778,7 @@ public class QueryStack {
if (targetParamDefinition == null) { if (targetParamDefinition == null) {
throw new InvalidRequestException("Unknown search parameter name: " + theSearchParam.getName() + '.' + targetParamName + "."); throw new InvalidRequestException("Unknown search parameter name: " + theSearchParam.getName() + '.' + targetParamName + ".");
} }
qp = toParameterType(targetParamDefinition); qp = toParameterType(targetParamDefinition);
qp.setValueAsQueryToken(myFhirContext, targetParamName, targetQualifier, targetValue); qp.setValueAsQueryToken(myFhirContext, targetParamName, targetQualifier, targetValue);
orValues.add(qp); orValues.add(qp);
@ -777,47 +788,50 @@ public class QueryStack {
if (targetParamDefinition == null) { if (targetParamDefinition == null) {
throw new InvalidRequestException("Unknown search parameter name: " + theSearchParam.getName() + "."); throw new InvalidRequestException("Unknown search parameter name: " + theSearchParam.getName() + ".");
} }
// 3. create the query // 3. create the query
Condition containedCondition = null; Condition containedCondition = null;
switch (targetParamDefinition.getParamType()) { switch (targetParamDefinition.getParamType()) {
case DATE: case DATE:
containedCondition = createPredicateDate(null, theResourceName, spnamePrefix, targetParamDefinition, containedCondition = createPredicateDate(null, theResourceName, spnamePrefix, targetParamDefinition,
orValues, theOperation, theRequestPartitionId); orValues, theOperation, theRequestPartitionId);
break; break;
case NUMBER: case NUMBER:
containedCondition = createPredicateNumber(null, theResourceName, spnamePrefix, targetParamDefinition, containedCondition = createPredicateNumber(null, theResourceName, spnamePrefix, targetParamDefinition,
orValues, theOperation, theRequestPartitionId); orValues, theOperation, theRequestPartitionId);
break; break;
case QUANTITY: case QUANTITY:
containedCondition = createPredicateQuantity(null, theResourceName, spnamePrefix, targetParamDefinition, containedCondition = createPredicateQuantity(null, theResourceName, spnamePrefix, targetParamDefinition,
orValues, theOperation, theRequestPartitionId); orValues, theOperation, theRequestPartitionId);
break; break;
case STRING: case STRING:
containedCondition = createPredicateString(null, theResourceName, spnamePrefix, targetParamDefinition, containedCondition = createPredicateString(null, theResourceName, spnamePrefix, targetParamDefinition,
orValues, theOperation, theRequestPartitionId); orValues, theOperation, theRequestPartitionId);
break; break;
case TOKEN: case TOKEN:
containedCondition = createPredicateToken(null, theResourceName, spnamePrefix, targetParamDefinition, containedCondition = createPredicateToken(null, theResourceName, spnamePrefix, targetParamDefinition,
orValues, theOperation, theRequestPartitionId); orValues, theOperation, theRequestPartitionId);
break; break;
case COMPOSITE: case COMPOSITE:
containedCondition = createPredicateComposite(null, theResourceName, spnamePrefix, targetParamDefinition, containedCondition = createPredicateComposite(null, theResourceName, spnamePrefix, targetParamDefinition,
orValues, theRequestPartitionId); orValues, theRequestPartitionId);
break; break;
case URI: case URI:
containedCondition = createPredicateUri(null, theResourceName, spnamePrefix, targetParamDefinition, containedCondition = createPredicateUri(null, theResourceName, spnamePrefix, targetParamDefinition,
orValues, theOperation, theRequest, theRequestPartitionId); orValues, theOperation, theRequest, theRequestPartitionId);
break; break;
default: case HAS:
throw new InvalidRequestException( case REFERENCE:
case SPECIAL:
default:
throw new InvalidRequestException(
"The search type:" + targetParamDefinition.getParamType() + " is not supported."); "The search type:" + targetParamDefinition.getParamType() + " is not supported.");
} }
return containedCondition; return containedCondition;
} }
@Nullable @Nullable
public Condition createPredicateResourceId(@Nullable DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theValues, String theResourceName, SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) { public Condition createPredicateResourceId(@Nullable DbColumn theSourceJoinColumn, List<List<IQueryParameterType>> theValues, String theResourceName, SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
ResourceIdPredicateBuilder builder = mySqlBuilder.newResourceIdBuilder(); ResourceIdPredicateBuilder builder = mySqlBuilder.newResourceIdBuilder();
@ -861,11 +875,11 @@ public class QueryStack {
} }
public Condition createPredicateString(@Nullable DbColumn theSourceJoinColumn, String theResourceName, public Condition createPredicateString(@Nullable DbColumn theSourceJoinColumn, String theResourceName,
String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList, String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) { SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName()); String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName());
StringPredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.STRING, theSourceJoinColumn, paramName, () -> mySqlBuilder.addStringPredicateBuilder(theSourceJoinColumn)).getResult(); StringPredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.STRING, theSourceJoinColumn, paramName, () -> mySqlBuilder.addStringPredicateBuilder(theSourceJoinColumn)).getResult();
if (theList.get(0).getMissing() != null) { if (theList.get(0).getMissing() != null) {
@ -971,8 +985,8 @@ public class QueryStack {
} }
public Condition createPredicateToken(@Nullable DbColumn theSourceJoinColumn, String theResourceName, public Condition createPredicateToken(@Nullable DbColumn theSourceJoinColumn, String theResourceName,
String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList, String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) { SearchFilterParser.CompareOperation theOperation, RequestPartitionId theRequestPartitionId) {
List<IQueryParameterType> tokens = new ArrayList<>(); List<IQueryParameterType> tokens = new ArrayList<>();
for (IQueryParameterType nextOr : theList) { for (IQueryParameterType nextOr : theList) {
@ -1011,7 +1025,7 @@ public class QueryStack {
if (tokens.isEmpty()) { if (tokens.isEmpty()) {
return null; return null;
} }
String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName()); String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName());
TokenPredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.TOKEN, theSourceJoinColumn, paramName, () -> mySqlBuilder.addTokenPredicateBuilder(theSourceJoinColumn)).getResult(); TokenPredicateBuilder join = createOrReusePredicateBuilder(PredicateBuilderTypeEnum.TOKEN, theSourceJoinColumn, paramName, () -> mySqlBuilder.addTokenPredicateBuilder(theSourceJoinColumn)).getResult();
@ -1025,12 +1039,12 @@ public class QueryStack {
} }
public Condition createPredicateUri(@Nullable DbColumn theSourceJoinColumn, String theResourceName, public Condition createPredicateUri(@Nullable DbColumn theSourceJoinColumn, String theResourceName,
String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList, String theSpnamePrefix, RuntimeSearchParam theSearchParam, List<? extends IQueryParameterType> theList,
SearchFilterParser.CompareOperation theOperation, RequestDetails theRequestDetails, SearchFilterParser.CompareOperation theOperation, RequestDetails theRequestDetails,
RequestPartitionId theRequestPartitionId) { RequestPartitionId theRequestPartitionId) {
String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName()); String paramName = getParamNameWithPrefix(theSpnamePrefix, theSearchParam.getName());
UriPredicateBuilder join = mySqlBuilder.addUriPredicateBuilder(theSourceJoinColumn); UriPredicateBuilder join = mySqlBuilder.addUriPredicateBuilder(theSourceJoinColumn);
if (theList.get(0).getMissing() != null) { if (theList.get(0).getMissing() != null) {
@ -1110,7 +1124,7 @@ public class QueryStack {
for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) { for (List<? extends IQueryParameterType> nextAnd : theAndOrParams) {
if (theSearchContainedMode.equals(SearchContainedModeEnum.TRUE)) if (theSearchContainedMode.equals(SearchContainedModeEnum.TRUE))
andPredicates.add(createPredicateReferenceForContainedResource(theSourceJoinColumn, theResourceName, theParamName, nextParamDef, nextAnd, null, theRequest, theRequestPartitionId)); andPredicates.add(createPredicateReferenceForContainedResource(theSourceJoinColumn, theResourceName, theParamName, nextParamDef, nextAnd, null, theRequest, theRequestPartitionId));
else else
andPredicates.add(createPredicateReference(theSourceJoinColumn, theResourceName, theParamName, nextAnd, null, theRequest, theRequestPartitionId)); andPredicates.add(createPredicateReference(theSourceJoinColumn, theResourceName, theParamName, nextAnd, null, theRequest, theRequestPartitionId));
} }
break; break;
@ -1204,6 +1218,46 @@ public class QueryStack {
mySqlBuilder.addPredicate(predicate); mySqlBuilder.addPredicate(predicate);
} }
private IQueryParameterType toParameterType(RuntimeSearchParam theParam) {
IQueryParameterType qp;
switch (theParam.getParamType()) {
case DATE:
qp = new DateParam();
break;
case NUMBER:
qp = new NumberParam();
break;
case QUANTITY:
qp = new QuantityParam();
break;
case STRING:
qp = new StringParam();
break;
case TOKEN:
qp = new TokenParam();
break;
case COMPOSITE:
List<RuntimeSearchParam> compositeOf = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, theParam);
if (compositeOf.size() != 2) {
throw new InternalErrorException("Parameter " + theParam.getName() + " has " + compositeOf.size() + " composite parts. Don't know how handlt this.");
}
IQueryParameterType leftParam = toParameterType(compositeOf.get(0));
IQueryParameterType rightParam = toParameterType(compositeOf.get(1));
qp = new CompositeParam<>(leftParam, rightParam);
break;
case URI:
qp = new UriParam();
break;
case HAS:
case REFERENCE:
case SPECIAL:
default:
throw new InvalidRequestException("The search type: " + theParam.getParamType() + " is not supported.");
}
return qp;
}
private enum PredicateBuilderTypeEnum { private enum PredicateBuilderTypeEnum {
DATE, COORDS, NUMBER, QUANTITY, REFERENCE, SOURCE, STRING, TOKEN, TAG DATE, COORDS, NUMBER, QUANTITY, REFERENCE, SOURCE, STRING, TOKEN, TAG
} }
@ -1343,48 +1397,11 @@ public class QueryStack {
return parameter.substring(parameter.indexOf(".") + 1); return parameter.substring(parameter.indexOf(".") + 1);
} }
private IQueryParameterType toParameterType(RuntimeSearchParam theParam) {
IQueryParameterType qp;
switch (theParam.getParamType()) {
case DATE:
qp = new DateParam();
break;
case NUMBER:
qp = new NumberParam();
break;
case QUANTITY:
qp = new QuantityParam();
break;
case STRING:
qp = new StringParam();
break;
case TOKEN:
qp = new TokenParam();
break;
case COMPOSITE:
List<RuntimeSearchParam> compositeOf = theParam.getCompositeOf();
if (compositeOf.size() != 2) {
throw new InternalErrorException("Parameter " + theParam.getName() + " has " + compositeOf.size() + " composite parts. Don't know how handlt this.");
}
IQueryParameterType leftParam = toParameterType(compositeOf.get(0));
IQueryParameterType rightParam = toParameterType(compositeOf.get(1));
qp = new CompositeParam<>(leftParam, rightParam);
break;
case URI:
qp = new UriParam();
break;
default:
throw new InvalidRequestException("The search type: " + theParam.getParamType() + " is not supported.");
}
return qp;
}
public static String getParamNameWithPrefix(String theSpnamePrefix, String theParamName) { public static String getParamNameWithPrefix(String theSpnamePrefix, String theParamName) {
if (isBlank(theSpnamePrefix)) if (isBlank(theSpnamePrefix))
return theParamName; return theParamName;
return theSpnamePrefix + "." + theParamName; return theSpnamePrefix + "." + theParamName;
} }
} }

View File

@ -55,9 +55,9 @@ import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryExecutor; import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryExecutor;
import ca.uhn.fhir.jpa.search.builder.sql.SqlObjectFactory; import ca.uhn.fhir.jpa.search.builder.sql.SqlObjectFactory;
import ca.uhn.fhir.jpa.search.lastn.IElasticsearchSvc; import ca.uhn.fhir.jpa.search.lastn.IElasticsearchSvc;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.Dstu3DistanceHelper; import ca.uhn.fhir.jpa.searchparam.util.Dstu3DistanceHelper;
import ca.uhn.fhir.jpa.searchparam.util.LastNParameterHelper; import ca.uhn.fhir.jpa.searchparam.util.LastNParameterHelper;
import ca.uhn.fhir.rest.api.SearchContainedModeEnum; import ca.uhn.fhir.rest.api.SearchContainedModeEnum;
@ -516,8 +516,7 @@ public class SearchBuilder implements ISearchBuilder {
} else { } else {
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceName); RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(myResourceName, theSort.getParamName());
RuntimeSearchParam param = mySearchParamRegistry.getSearchParamByName(resourceDef, theSort.getParamName());
if (param == null) { if (param == null) {
String msg = myContext.getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "invalidSortParameter", theSort.getParamName(), getResourceName(), mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(getResourceName())); String msg = myContext.getLocalizer().getMessageSanitized(BaseHapiFhirResourceDao.class, "invalidSortParameter", theSort.getParamName(), getResourceName(), mySearchParamRegistry.getValidSearchParameterNamesIncludingMeta(getResourceName()));
throw new InvalidRequestException(msg); throw new InvalidRequestException(msg);
@ -546,17 +545,17 @@ public class SearchBuilder implements ISearchBuilder {
theQueryStack.addSortOnQuantity(myResourceName, theSort.getParamName(), ascending); theQueryStack.addSortOnQuantity(myResourceName, theSort.getParamName(), ascending);
break; break;
case COMPOSITE: case COMPOSITE:
List<RuntimeSearchParam> compositList = param.getCompositeOf(); List<RuntimeSearchParam> compositeList = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, param);
if (compositList == null) { if (compositeList == null) {
throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName() + " is not defined by the resource " + myResourceName); throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName() + " is not defined by the resource " + myResourceName);
} }
if (compositList.size() != 2) { if (compositeList.size() != 2) {
throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName() throw new InvalidRequestException("The composite _sort parameter " + theSort.getParamName()
+ " must have 2 composite types declared in parameter annotation, found " + " must have 2 composite types declared in parameter annotation, found "
+ compositList.size()); + compositeList.size());
} }
RuntimeSearchParam left = compositList.get(0); RuntimeSearchParam left = compositeList.get(0);
RuntimeSearchParam right = compositList.get(1); RuntimeSearchParam right = compositeList.get(1);
createCompositeSort(theQueryStack, myResourceName, left.getParamType(), left.getName(), ascending); createCompositeSort(theQueryStack, myResourceName, left.getParamType(), left.getName(), ascending);
createCompositeSort(theQueryStack, myResourceName, right.getParamType(), right.getName(), ascending); createCompositeSort(theQueryStack, myResourceName, right.getParamType(), right.getName(), ascending);
@ -835,7 +834,7 @@ public class SearchBuilder implements ISearchBuilder {
String paramName = nextInclude.getParamName(); String paramName = nextInclude.getParamName();
if (isNotBlank(paramName)) { if (isNotBlank(paramName)) {
param = mySearchParamRegistry.getSearchParamByName(def, paramName); param = mySearchParamRegistry.getActiveSearchParam(resType, paramName);
} else { } else {
param = null; param = null;
} }
@ -969,7 +968,7 @@ public class SearchBuilder implements ISearchBuilder {
// Since we're going to remove elements below // Since we're going to remove elements below
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList)); theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
List<JpaRuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet()); List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
if (activeUniqueSearchParams.size() > 0) { if (activeUniqueSearchParams.size() > 0) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -43,8 +43,9 @@ import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder; import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams; import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams;
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.rest.api.SearchContainedModeEnum; import ca.uhn.fhir.rest.api.SearchContainedModeEnum;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster; import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
@ -367,7 +368,7 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder {
boolean isMeta = ResourceMetaParams.RESOURCE_META_PARAMS.containsKey(chain); boolean isMeta = ResourceMetaParams.RESOURCE_META_PARAMS.containsKey(chain);
RuntimeSearchParam param = null; RuntimeSearchParam param = null;
if (!isMeta) { if (!isMeta) {
param = mySearchParamRegistry.getSearchParamByName(typeDef, chain); param = mySearchParamRegistry.getActiveSearchParam(nextType, chain);
if (param == null) { if (param == null) {
ourLog.debug("Type {} doesn't have search param {}", nextType, param); ourLog.debug("Type {} doesn't have search param {}", nextType, param);
continue; continue;
@ -431,8 +432,7 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder {
} }
if (resourceTypes.isEmpty()) { if (resourceTypes.isEmpty()) {
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(theResourceName); RuntimeSearchParam searchParamByName = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
RuntimeSearchParam searchParamByName = mySearchParamRegistry.getSearchParamByName(resourceDef, theParamName);
if (searchParamByName == null) { if (searchParamByName == null) {
throw new InternalErrorException("Could not find parameter " + theParamName); throw new InternalErrorException("Could not find parameter " + theParamName);
} }
@ -495,8 +495,7 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder {
} }
public List<String> createResourceLinkPaths(String theResourceName, String theParamName) { public List<String> createResourceLinkPaths(String theResourceName, String theParamName) {
RuntimeResourceDefinition resourceDef = getFhirContext().getResourceDefinition(theResourceName); RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceName, theParamName);
RuntimeSearchParam param = mySearchParamRegistry.getSearchParamByName(resourceDef, theParamName);
List<String> path = param.getPathsSplit(); List<String> path = param.getPathsSplit();
/* /*
@ -558,7 +557,7 @@ public class ResourceLinkPredicateBuilder extends BaseJoiningPredicateBuilder {
qp = new TokenParam(); qp = new TokenParam();
break; break;
case COMPOSITE: case COMPOSITE:
List<RuntimeSearchParam> compositeOf = theParam.getCompositeOf(); List<RuntimeSearchParam> compositeOf = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, theParam);
if (compositeOf.size() != 2) { if (compositeOf.size() != 2) {
throw new InternalErrorException("Parameter " + theParam.getName() + " has " + compositeOf.size() + " composite parts. Don't know how handlt this."); throw new InternalErrorException("Parameter " + theParam.getName() + " has " + compositeOf.size() + " composite parts. Don't know how handlt this.");
} }

View File

@ -36,7 +36,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.sched.HapiJob; import ca.uhn.fhir.jpa.model.sched.HapiJob;
import ca.uhn.fhir.jpa.model.sched.ISchedulerService; import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition; import ca.uhn.fhir.jpa.model.sched.ScheduledJobDefinition;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;

View File

@ -25,10 +25,9 @@ import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc; import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc;
import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc; import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionLoader; import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionLoader;
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionRegistry; import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionRegistry;
import ca.uhn.fhir.jpa.term.ValueSetExpansionR4Test;
import ca.uhn.fhir.jpa.util.CircularQueueCaptureQueriesListener; import ca.uhn.fhir.jpa.util.CircularQueueCaptureQueriesListener;
import ca.uhn.fhir.jpa.util.MemoryCacheService; import ca.uhn.fhir.jpa.util.MemoryCacheService;
import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Bundle;
@ -50,7 +49,6 @@ import org.apache.commons.io.IOUtils;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;
import org.hibernate.search.backend.lucene.cfg.LuceneBackendSettings; import org.hibernate.search.backend.lucene.cfg.LuceneBackendSettings;
import org.hibernate.search.backend.lucene.cfg.LuceneIndexSettings; import org.hibernate.search.backend.lucene.cfg.LuceneIndexSettings;
import org.hibernate.search.engine.cfg.BackendSettings; import org.hibernate.search.engine.cfg.BackendSettings;
@ -71,7 +69,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Pageable;
import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;

View File

@ -17,12 +17,12 @@ import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamTokenDao;
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao; import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao; import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistryController;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionLoader; import ca.uhn.fhir.jpa.subscription.match.registry.SubscriptionLoader;
import ca.uhn.fhir.jpa.util.ResourceCountCache; import ca.uhn.fhir.jpa.util.ResourceCountCache;
@ -60,12 +60,10 @@ import ca.uhn.fhir.model.dstu2.resource.ValueSet;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hibernate.search.mapper.orm.Search; import org.hibernate.search.mapper.orm.Search;
import org.hibernate.search.mapper.orm.session.SearchSession; import org.hibernate.search.mapper.orm.session.SearchSession;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -82,6 +80,7 @@ import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
@ -94,6 +93,8 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@Autowired @Autowired
protected ISearchParamRegistry mySearchParamRegistry; protected ISearchParamRegistry mySearchParamRegistry;
@Autowired @Autowired
protected ISearchParamRegistryController mySearchParamRegistryController;
@Autowired
protected ApplicationContext myAppCtx; protected ApplicationContext myAppCtx;
@Autowired @Autowired
protected IResourceReindexingSvc myResourceReindexingSvc; protected IResourceReindexingSvc myResourceReindexingSvc;
@ -267,7 +268,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
if (stream == null) { if (stream == null) {
fail("Unable to load resource: " + resourceName); fail("Unable to load resource: " + resourceName);
} }
String string = IOUtils.toString(stream, "UTF-8"); String string = IOUtils.toString(stream, StandardCharsets.UTF_8);
IParser newJsonParser = EncodingEnum.detectEncodingNoDefault(string).newParser(myFhirCtx); IParser newJsonParser = EncodingEnum.detectEncodingNoDefault(string).newParser(myFhirCtx);
return newJsonParser.parseResource(type, string); return newJsonParser.parseResource(type, string);
} }

View File

@ -254,7 +254,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
mySearchParameterDao.update(numberParameter); mySearchParameterDao.update(numberParameter);
// This fires every 10 seconds // This fires every 10 seconds
mySearchParamRegistry.refreshCacheIfNecessary(); mySearchParamRegistryController.refreshCacheIfNecessary();
Patient patient = new Patient(); Patient patient = new Patient();
patient.setId("future-appointment-count-pt"); patient.setId("future-appointment-count-pt");

View File

@ -33,13 +33,12 @@ import ca.uhn.fhir.jpa.dao.data.ITermValueSetDao;
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest; import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test; import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3; import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl; import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
import ca.uhn.fhir.jpa.term.TermConceptMappingSvcImpl; import ca.uhn.fhir.jpa.term.TermConceptMappingSvcImpl;

View File

@ -5,7 +5,7 @@ import ca.uhn.fhir.context.phonetic.PhoneticEncoderEnum;
import ca.uhn.fhir.jpa.api.config.DaoConfig; import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.util.HapiExtensions; import ca.uhn.fhir.util.HapiExtensions;
import org.apache.commons.codec.language.Soundex; import org.apache.commons.codec.language.Soundex;

View File

@ -1605,7 +1605,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
verify(interceptor, times(1)).invoke(any(), paramsCaptor.capture()); verify(interceptor, times(1)).invoke(any(), paramsCaptor.capture());
StorageProcessingMessage msg = paramsCaptor.getValue().get(StorageProcessingMessage.class); StorageProcessingMessage msg = paramsCaptor.getValue().get(StorageProcessingMessage.class);
assertThat(msg.getMessage(), containsString("refers to unknown component foo, ignoring this parameter")); assertThat(msg.getMessage(), containsString("ignoring this parameter"));
} finally { } finally {
myInterceptorRegistry.unregisterInterceptor(interceptor); myInterceptorRegistry.unregisterInterceptor(interceptor);

View File

@ -48,7 +48,7 @@ import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4; import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;

View File

@ -13,7 +13,7 @@ import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest; import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.IParser;
@ -23,7 +23,6 @@ import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.TokenParamModifier; import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
@ -43,7 +42,6 @@ import org.hl7.fhir.r4.model.Meta;
import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.ValueSet; import org.hl7.fhir.r4.model.ValueSet;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -14,7 +14,7 @@ import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
import ca.uhn.fhir.jpa.entity.TermConcept; import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.dao.r4; package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
@ -10,9 +11,9 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl; import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.util.SpringObjectCaster; import ca.uhn.fhir.jpa.util.SpringObjectCaster;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateParam;
@ -23,11 +24,9 @@ import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException; import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.HapiExtensions; import ca.uhn.fhir.util.HapiExtensions;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -707,7 +706,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class); ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
svc.initExecutor(); svc.initExecutor();
List<JpaRuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation"); List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
assertEquals(0, uniqueSearchParams.size()); assertEquals(0, uniqueSearchParams.size());
Patient pt1 = new Patient(); Patient pt1 = new Patient();
@ -1487,14 +1486,16 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
@Test @Test
public void testDetectUniqueSearchParams() { public void testDetectUniqueSearchParams() {
createUniqueBirthdateAndGenderSps(); createUniqueBirthdateAndGenderSps();
List<JpaRuntimeSearchParam> params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient"); List<RuntimeSearchParam> params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
assertEquals(1, params.size()); assertEquals(1, params.size());
assertEquals(params.get(0).isUnique(), true); assertEquals(params.get(0).isUnique(), true);
assertEquals(2, params.get(0).getCompositeOf().size()); assertEquals(2, params.get(0).getComponents().size());
// Should be alphabetical order // Should be alphabetical order
assertEquals("birthdate", params.get(0).getCompositeOf().get(0).getName()); List<RuntimeSearchParam> compositeParams = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, params.get(0));
assertEquals("gender", params.get(0).getCompositeOf().get(1).getName()); assertEquals("birthdate", compositeParams.get(0).getName());
assertEquals("gender", compositeParams.get(1).getName());
} }
@Test @Test

View File

@ -15,13 +15,13 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantityNormalized
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil; import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor; import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef; import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4; import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistryController;
import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache; import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.HapiExtensions; import ca.uhn.fhir.util.HapiExtensions;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.hl7.fhir.r4.model.BooleanType; import org.hl7.fhir.r4.model.BooleanType;
@ -37,6 +37,7 @@ import org.hl7.fhir.r4.model.Quantity;
import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.SearchParameter; import org.hl7.fhir.r4.model.SearchParameter;
import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.StringType;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -44,7 +45,6 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -327,7 +327,7 @@ public class SearchParamExtractorR4Test {
public void testExtensionContainingReference() { public void testExtensionContainingReference() {
String path = "Patient.extension('http://patext').value.as(Reference)"; String path = "Patient.extension('http://patext').value.as(Reference)";
RuntimeSearchParam sp = new RuntimeSearchParam("extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE); RuntimeSearchParam sp = new RuntimeSearchParam(null, null, "extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
mySearchParamRegistry.addSearchParam(sp); mySearchParamRegistry.addSearchParam(sp);
Patient patient = new Patient(); Patient patient = new Patient();
@ -395,7 +395,7 @@ public class SearchParamExtractorR4Test {
assertEquals(2, list.size()); assertEquals(2, list.size());
} }
private static class MySearchParamRegistry implements ISearchParamRegistry { private static class MySearchParamRegistry implements ISearchParamRegistry, ISearchParamRegistryController {
private List<RuntimeSearchParam> myExtraSearchParams = new ArrayList<>(); private List<RuntimeSearchParam> myExtraSearchParams = new ArrayList<>();
@ -416,7 +416,6 @@ public class SearchParamExtractorR4Test {
return new ResourceChangeResult(); return new ResourceChangeResult();
} }
@Override
public ReadOnlySearchParamCache getActiveSearchParams() { public ReadOnlySearchParamCache getActiveSearchParams() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -441,12 +440,18 @@ public class SearchParamExtractorR4Test {
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -455,16 +460,6 @@ public class SearchParamExtractorR4Test {
// nothing // nothing
} }
@Override
public RuntimeSearchParam getSearchParamByName(RuntimeResourceDefinition theResourceDef, String theParamName) {
return null;
}
@Override
public Collection<RuntimeSearchParam> getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef) {
return null;
}
@Override @Override
public void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) { public void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {
// nothing // nothing

View File

@ -189,7 +189,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
ourClient.update().resource(numberParameter).execute(); ourClient.update().resource(numberParameter).execute();
// This fires every 10 seconds // This fires every 10 seconds
mySearchParamRegistry.refreshCacheIfNecessary(); mySearchParamRegistryController.refreshCacheIfNecessary();
Patient patient = new Patient(); Patient patient = new Patient();
patient.setId("future-appointment-count-pt"); patient.setId("future-appointment-count-pt");

View File

@ -393,7 +393,9 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE); fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(fooSp, mySrd); mySearchParameterDao.create(fooSp, mySrd);
myCaptureQueriesListener.clear();
mySearchParamRegistry.forceRefresh(); mySearchParamRegistry.forceRefresh();
myCaptureQueriesListener.logAllQueriesForCurrentThread();
Patient pat = new Patient(); Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE); pat.setGender(AdministrativeGender.MALE);

View File

@ -629,7 +629,7 @@ public class ResourceProviderHasParamR4Test extends BaseResourceProviderR4Test {
try (CloseableHttpResponse response = ourHttpClient.execute(get)) { try (CloseableHttpResponse response = ourHttpClient.execute(get)) {
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(resp); ourLog.info("Response was: {}", resp);
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, resp); Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, resp);
ids = toUnqualifiedVersionlessIdValues(bundle); ids = toUnqualifiedVersionlessIdValues(bundle);
} }

View File

@ -13,11 +13,10 @@ import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.entity.ResourceReindexJobEntity; import ca.uhn.fhir.jpa.entity.ResourceReindexJobEntity;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.sched.ISchedulerService; import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;

View File

@ -5,14 +5,12 @@ import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.config.TestDstu3Config; import ca.uhn.fhir.jpa.config.TestDstu3Config;
import ca.uhn.fhir.jpa.dao.BaseJpaTest; import ca.uhn.fhir.jpa.dao.BaseJpaTest;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.Dstu3DistanceHelper; import ca.uhn.fhir.jpa.searchparam.util.Dstu3DistanceHelper;
import ca.uhn.fhir.rest.param.QuantityParam; import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceParam; import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.model.Condition; import org.hl7.fhir.dstu3.model.Condition;
import org.hl7.fhir.dstu3.model.Location; import org.hl7.fhir.dstu3.model.Location;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -41,7 +39,7 @@ public class MatchUrlServiceTest extends BaseJpaTest {
public void testTranslateMatchUrl() { public void testTranslateMatchUrl() {
RuntimeResourceDefinition resourceDef = ourCtx.getResourceDefinition(Condition.class); RuntimeResourceDefinition resourceDef = ourCtx.getResourceDefinition(Condition.class);
ISearchParamRegistry searchParamRegistry = mock(ISearchParamRegistry.class); ISearchParamRegistry searchParamRegistry = mock(ISearchParamRegistry.class);
when(searchParamRegistry.getSearchParamByName(any(RuntimeResourceDefinition.class), eq("patient"))).thenReturn(resourceDef.getSearchParam("patient")); when(searchParamRegistry.getActiveSearchParam(any(), eq("patient"))).thenReturn(resourceDef.getSearchParam("patient"));
SearchParameterMap match = myMatchUrlService.translateMatchUrl("Condition?patient=304&_lastUpdated=>2011-01-01T11:12:21.0000Z", resourceDef); SearchParameterMap match = myMatchUrlService.translateMatchUrl("Condition?patient=304&_lastUpdated=>2011-01-01T11:12:21.0000Z", resourceDef);
assertEquals("2011-01-01T11:12:21.0000Z", match.getLastUpdated().getLowerBound().getValueAsString()); assertEquals("2011-01-01T11:12:21.0000Z", match.getLastUpdated().getLowerBound().getValueAsString());
assertEquals(ReferenceParam.class, match.get("patient").get(0).get(0).getClass()); assertEquals(ReferenceParam.class, match.get("patient").get(0).get(0).getClass());

View File

@ -15,7 +15,7 @@ import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink; import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc; import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc; import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4; import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
@ -144,13 +144,13 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-test-utilities</artifactId> <artifactId>hapi-fhir-test-utilities</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-test-utilities</artifactId> <artifactId>hapi-fhir-jpaserver-test-utilities</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>
@ -55,13 +55,13 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-test-utilities</artifactId> <artifactId>hapi-fhir-test-utilities</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-jpaserver-test-utilities</artifactId> <artifactId>hapi-fhir-jpaserver-test-utilities</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -64,7 +64,7 @@ import ca.uhn.fhir.jpa.mdm.svc.candidate.MdmGoldenResourceFindingSvc;
import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByEidSvc; import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByEidSvc;
import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByLinkSvc; import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByLinkSvc;
import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByExampleSvc; import ca.uhn.fhir.jpa.mdm.svc.candidate.FindCandidateByExampleSvc;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.validation.IResourceLoader; import ca.uhn.fhir.validation.IResourceLoader;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -153,7 +153,7 @@ public class MdmConsumerConfig {
} }
@Bean @Bean
MdmRuleValidator mdmRuleValidator(FhirContext theFhirContext, ISearchParamRetriever theSearchParamRetriever) { MdmRuleValidator mdmRuleValidator(FhirContext theFhirContext, ISearchParamRegistry theSearchParamRetriever) {
return new MdmRuleValidator(theFhirContext, theSearchParamRetriever); return new MdmRuleValidator(theFhirContext, theSearchParamRetriever);
} }

View File

@ -32,7 +32,7 @@ import ca.uhn.fhir.jpa.mdm.svc.MdmGoldenResourceDeletingSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc; import ca.uhn.fhir.jpa.mdm.svc.MdmSearchParamSvc;
import ca.uhn.fhir.jpa.mdm.svc.MdmSubmitSvcImpl; import ca.uhn.fhir.jpa.mdm.svc.MdmSubmitSvcImpl;
import ca.uhn.fhir.jpa.subscription.channel.api.IChannelFactory; import ca.uhn.fhir.jpa.subscription.channel.api.IChannelFactory;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -51,7 +51,7 @@ public class MdmSubmitterConfig {
} }
@Bean @Bean
MdmRuleValidator mdmRuleValidator(FhirContext theFhirContext, ISearchParamRetriever theSearchParamRetriever) { MdmRuleValidator mdmRuleValidator(FhirContext theFhirContext, ISearchParamRegistry theSearchParamRetriever) {
return new MdmRuleValidator(theFhirContext, theSearchParamRetriever); return new MdmRuleValidator(theFhirContext, theSearchParamRetriever);
} }

View File

@ -30,7 +30,7 @@ import ca.uhn.fhir.jpa.dao.SearchBuilderFactory;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService; import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -72,6 +72,7 @@ public class ResourceChangeEvent implements IResourceChangeEvent {
return myDeletedResourceIds; return myDeletedResourceIds;
} }
@Override
public boolean isEmpty() { public boolean isEmpty() {
return myCreatedResourceIds.isEmpty() && myUpdatedResourceIds.isEmpty() && myDeletedResourceIds.isEmpty(); return myCreatedResourceIds.isEmpty() && myUpdatedResourceIds.isEmpty() && myDeletedResourceIds.isEmpty();
} }

View File

@ -1,88 +0,0 @@
package ca.uhn.fhir.jpa.searchparam;
/*-
* #%L
* HAPI FHIR Search Parameters
* %%
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class JpaRuntimeSearchParam extends RuntimeSearchParam {
private final boolean myUnique;
private final List<Component> myComponents;
/**
* Constructor
*/
public JpaRuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, boolean theUnique, List<Component> theComponents, Collection<String> theBase) {
super(theId, theUri, theName, theDescription, thePath, theParamType, createCompositeList(theParamType), theProvidesMembershipInCompartments, theTargets, theStatus, theBase);
myUnique = theUnique;
myComponents = Collections.unmodifiableList(theComponents);
}
public List<Component> getComponents() {
return myComponents;
}
public boolean isUnique() {
return myUnique;
}
public static class Component {
private final String myExpression;
private final IBaseReference myReference;
public Component(String theExpression, IBaseReference theReference) {
myExpression = theExpression;
myReference = theReference;
}
public String getExpression() {
return myExpression;
}
public IBaseReference getReference() {
return myReference;
}
}
private static ArrayList<RuntimeSearchParam> createCompositeList(RestSearchParameterTypeEnum theParamType) {
if (theParamType == RestSearchParameterTypeEnum.COMPOSITE) {
return new ArrayList<>();
} else {
return null;
}
}
}

View File

@ -24,7 +24,8 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.model.util.JpaConstants; import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.model.api.IQueryParameterAnd; import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.Include; import ca.uhn.fhir.model.api.Include;
@ -99,7 +100,7 @@ public class MatchUrlService {
} }
} }
} else if (Constants.PARAM_HAS.equals(nextParamName)) { } else if (Constants.PARAM_HAS.equals(nextParamName)) {
IQueryParameterAnd<?> param = ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.HAS, nextParamName, paramList); IQueryParameterAnd<?> param = JpaParamUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.HAS, nextParamName, paramList);
paramMap.add(nextParamName, param); paramMap.add(nextParamName, param);
} else if (Constants.PARAM_COUNT.equals(nextParamName)) { } else if (Constants.PARAM_COUNT.equals(nextParamName)) {
if (paramList != null && paramList.size() > 0 && paramList.get(0).size() > 0) { if (paramList != null && paramList.size() > 0 && paramList.get(0).size() > 0) {
@ -127,23 +128,23 @@ public class MatchUrlService {
type.setValuesAsQueryTokens(myContext, nextParamName, (paramList)); type.setValuesAsQueryTokens(myContext, nextParamName, (paramList));
paramMap.add(nextParamName, type); paramMap.add(nextParamName, type);
} else if (Constants.PARAM_SOURCE.equals(nextParamName)) { } else if (Constants.PARAM_SOURCE.equals(nextParamName)) {
IQueryParameterAnd<?> param = ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.TOKEN, nextParamName, paramList); IQueryParameterAnd<?> param = JpaParamUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.TOKEN, nextParamName, paramList);
paramMap.add(nextParamName, param); paramMap.add(nextParamName, param);
} else if (JpaConstants.PARAM_DELETE_EXPUNGE.equals(nextParamName)) { } else if (JpaConstants.PARAM_DELETE_EXPUNGE.equals(nextParamName)) {
paramMap.setDeleteExpunge(true); paramMap.setDeleteExpunge(true);
} else if (Constants.PARAM_LIST.equals(nextParamName)) { } else if (Constants.PARAM_LIST.equals(nextParamName)) {
IQueryParameterAnd<?> param = ParameterUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.TOKEN, nextParamName, paramList); IQueryParameterAnd<?> param = JpaParamUtil.parseQueryParams(myContext, RestSearchParameterTypeEnum.TOKEN, nextParamName, paramList);
paramMap.add(nextParamName, param); paramMap.add(nextParamName, param);
} else if (nextParamName.startsWith("_")) { } else if (nextParamName.startsWith("_")) {
// ignore these since they aren't search params (e.g. _sort) // ignore these since they aren't search params (e.g. _sort)
} else { } else {
RuntimeSearchParam paramDef = mySearchParamRegistry.getSearchParamByName(theResourceDefinition, nextParamName); RuntimeSearchParam paramDef = mySearchParamRegistry.getActiveSearchParam(theResourceDefinition.getName(), nextParamName);
if (paramDef == null) { if (paramDef == null) {
throw new InvalidRequestException( throw new InvalidRequestException(
"Failed to parse match URL[" + theMatchUrl + "] - Resource type " + theResourceDefinition.getName() + " does not have a parameter with name: " + nextParamName); "Failed to parse match URL[" + theMatchUrl + "] - Resource type " + theResourceDefinition.getName() + " does not have a parameter with name: " + nextParamName);
} }
IQueryParameterAnd<?> param = ParameterUtil.parseQueryParams(myContext, paramDef, nextParamName, paramList); IQueryParameterAnd<?> param = JpaParamUtil.parseQueryParams(mySearchParamRegistry, myContext, paramDef, nextParamName, paramList);
paramMap.add(nextParamName, param); paramMap.add(nextParamName, param);
} }
} }

View File

@ -39,7 +39,7 @@ import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryResourceMatcher; import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryResourceMatcher;
import ca.uhn.fhir.jpa.searchparam.matcher.IndexedSearchParamExtractor; import ca.uhn.fhir.jpa.searchparam.matcher.IndexedSearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher; import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl; import ca.uhn.fhir.jpa.searchparam.registry.SearchParamRegistryImpl;
import ca.uhn.fhir.jpa.searchparam.registry.SearchParameterCanonicalizer; import ca.uhn.fhir.jpa.searchparam.registry.SearchParameterCanonicalizer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;

View File

@ -41,7 +41,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil; import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants; import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.model.primitive.BoundCodeDt; import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.model.dstu2.composite.ContactPointDt; import ca.uhn.fhir.model.dstu2.composite.ContactPointDt;
import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.FhirTerser;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.hl7.fhir.dstu3.context.IWorkerContext; import org.hl7.fhir.dstu3.context.IWorkerContext;
import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext; import org.hl7.fhir.dstu3.hapi.ctx.HapiWorkerContext;

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.exceptions.PathEngineException;

View File

@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;

View File

@ -43,18 +43,15 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.model.entity.ResourceLink; import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable; import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster; import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId; import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import ca.uhn.fhir.util.StringUtil;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -27,7 +27,7 @@ import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam; import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.model.api.IQueryParameterType; import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;

View File

@ -1,77 +0,0 @@
package ca.uhn.fhir.jpa.searchparam.registry;
/*
* #%L
* HAPI FHIR Search Parameters
* %%
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public interface ISearchParamRegistry extends ISearchParamRetriever {
/**
* Request that the cache be refreshed now, in the current thread
*/
void forceRefresh();
/**
* @return the number of search parameter entries changed
*/
ResourceChangeResult refreshCacheIfNecessary();
ReadOnlySearchParamCache getActiveSearchParams();
List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames);
List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName);
/**
* Request that the cache be refreshed at the next convenient time (in a different thread)
*/
void requestRefresh();
RuntimeSearchParam getSearchParamByName(RuntimeResourceDefinition theResourceDef, String theParamName);
Collection<RuntimeSearchParam> getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef);
/**
* When indexing a HumanName, if a StringEncoder is set in the context, then the "phonetic" search parameter will normalize
* the String using this encoder.
*
* @since 5.1.0
*/
void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder);
/**
* Returns a collection containing all of the valid active search parameters. This method is intended for
* creating error messages for users as opposed to actual search processing. It will include meta parameters
* such as <code>_id</code> and <code>_lastUpdated</code>.
*/
default Collection<String> getValidSearchParameterNamesIncludingMeta(String theResourceName) {
return getActiveSearchParams().getValidSearchParameterNamesIncludingMeta(theResourceName);
}
}

View File

@ -1,8 +1,8 @@
package ca.uhn.fhir.rest.server.util; package ca.uhn.fhir.jpa.searchparam.registry;
/*- /*-
* #%L * #%L
* HAPI FHIR - Server Framework * HAPI FHIR Search Parameters
* %% * %%
* Copyright (C) 2014 - 2021 Smile CDR, Inc. * Copyright (C) 2014 - 2021 Smile CDR, Inc.
* %% * %%
@ -18,25 +18,12 @@ package ca.uhn.fhir.rest.server.util;
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* #L% * #L%
*/
import ca.uhn.fhir.context.RuntimeSearchParam;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
public interface ISearchParamRetriever {
/**
* @return Returns {@literal null} if no match
*/ */
@Nullable
RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName);
/** import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
* @return Returns all active search params for the given resource
*/ public interface ISearchParamRegistryController {
@Nonnull
Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName); ResourceChangeResult refreshCacheIfNecessary();
} }

View File

@ -26,10 +26,8 @@ import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorService; import ca.uhn.fhir.interceptor.api.IInterceptorService;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage; import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -41,29 +39,32 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class JpaSearchParamCache { public class JpaSearchParamCache {
private static final Logger ourLog = LoggerFactory.getLogger(JpaSearchParamCache.class); private static final Logger ourLog = LoggerFactory.getLogger(JpaSearchParamCache.class);
private volatile Map<String, List<JpaRuntimeSearchParam>> myActiveUniqueSearchParams = Collections.emptyMap(); private volatile Map<String, List<RuntimeSearchParam>> myActiveUniqueSearchParams = Collections.emptyMap();
private volatile Map<String, Map<Set<String>, List<JpaRuntimeSearchParam>>> myActiveParamNamesToUniqueSearchParams = Collections.emptyMap(); private volatile Map<String, Map<Set<String>, List<RuntimeSearchParam>>> myActiveParamNamesToUniqueSearchParams = Collections.emptyMap();
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
List<JpaRuntimeSearchParam> retval = myActiveUniqueSearchParams.get(theResourceName); List<RuntimeSearchParam> retval = myActiveUniqueSearchParams.get(theResourceName);
if (retval == null) { if (retval == null) {
retval = Collections.emptyList(); retval = Collections.emptyList();
} }
return retval; return retval;
} }
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
Map<Set<String>, List<JpaRuntimeSearchParam>> paramNamesToParams = myActiveParamNamesToUniqueSearchParams.get(theResourceName); Map<Set<String>, List<RuntimeSearchParam>> paramNamesToParams = myActiveParamNamesToUniqueSearchParams.get(theResourceName);
if (paramNamesToParams == null) { if (paramNamesToParams == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<JpaRuntimeSearchParam> retVal = paramNamesToParams.get(theParamNames); List<RuntimeSearchParam> retVal = paramNamesToParams.get(theParamNames);
if (retVal == null) { if (retVal == null) {
retVal = Collections.emptyList(); retVal = Collections.emptyList();
} }
@ -71,18 +72,18 @@ public class JpaSearchParamCache {
} }
void populateActiveSearchParams(IInterceptorService theInterceptorBroadcaster, IPhoneticEncoder theDefaultPhoneticEncoder, RuntimeSearchParamCache theActiveSearchParams) { void populateActiveSearchParams(IInterceptorService theInterceptorBroadcaster, IPhoneticEncoder theDefaultPhoneticEncoder, RuntimeSearchParamCache theActiveSearchParams) {
Map<String, List<JpaRuntimeSearchParam>> activeUniqueSearchParams = new HashMap<>(); Map<String, List<RuntimeSearchParam>> activeUniqueSearchParams = new HashMap<>();
Map<String, Map<Set<String>, List<JpaRuntimeSearchParam>>> activeParamNamesToUniqueSearchParams = new HashMap<>(); Map<String, Map<Set<String>, List<RuntimeSearchParam>>> activeParamNamesToUniqueSearchParams = new HashMap<>();
Map<String, RuntimeSearchParam> idToRuntimeSearchParam = new HashMap<>(); Map<String, RuntimeSearchParam> idToRuntimeSearchParam = new HashMap<>();
List<JpaRuntimeSearchParam> jpaSearchParams = new ArrayList<>(); List<RuntimeSearchParam> jpaSearchParams = new ArrayList<>();
/* /*
* Loop through parameters and find JPA params * Loop through parameters and find JPA params
*/ */
for (String theResourceName : theActiveSearchParams.getResourceNameKeys()) { for (String theResourceName : theActiveSearchParams.getResourceNameKeys()) {
Map<String, RuntimeSearchParam> searchParamMap = theActiveSearchParams.getSearchParamMap(theResourceName); Map<String, RuntimeSearchParam> searchParamMap = theActiveSearchParams.getSearchParamMap(theResourceName);
List<JpaRuntimeSearchParam> uniqueSearchParams = activeUniqueSearchParams.computeIfAbsent(theResourceName, k -> new ArrayList<>()); List<RuntimeSearchParam> uniqueSearchParams = activeUniqueSearchParams.computeIfAbsent(theResourceName, k -> new ArrayList<>());
Collection<RuntimeSearchParam> nextSearchParamsForResourceName = searchParamMap.values(); Collection<RuntimeSearchParam> nextSearchParamsForResourceName = searchParamMap.values();
ourLog.trace("Resource {} has {} params", theResourceName, searchParamMap.size()); ourLog.trace("Resource {} has {} params", theResourceName, searchParamMap.size());
@ -94,13 +95,14 @@ public class JpaSearchParamCache {
if (nextCandidate.getId() != null) { if (nextCandidate.getId() != null) {
idToRuntimeSearchParam.put(nextCandidate.getId().toUnqualifiedVersionless().getValue(), nextCandidate); idToRuntimeSearchParam.put(nextCandidate.getId().toUnqualifiedVersionless().getValue(), nextCandidate);
} }
if (isNotBlank(nextCandidate.getUri())) {
idToRuntimeSearchParam.put(nextCandidate.getUri(), nextCandidate);
}
if (nextCandidate instanceof JpaRuntimeSearchParam) { RuntimeSearchParam nextCandidateCasted = nextCandidate;
JpaRuntimeSearchParam nextCandidateCasted = (JpaRuntimeSearchParam) nextCandidate; jpaSearchParams.add(nextCandidateCasted);
jpaSearchParams.add(nextCandidateCasted); if (nextCandidateCasted.isUnique()) {
if (nextCandidateCasted.isUnique()) { uniqueSearchParams.add(nextCandidateCasted);
uniqueSearchParams.add(nextCandidateCasted);
}
} }
setPhoneticEncoder(theDefaultPhoneticEncoder, nextCandidate); setPhoneticEncoder(theDefaultPhoneticEncoder, nextCandidate);
@ -111,25 +113,19 @@ public class JpaSearchParamCache {
ourLog.trace("Have {} search params loaded", idToRuntimeSearchParam.size()); ourLog.trace("Have {} search params loaded", idToRuntimeSearchParam.size());
Set<String> haveSeen = new HashSet<>(); Set<String> haveSeen = new HashSet<>();
for (JpaRuntimeSearchParam next : jpaSearchParams) { for (RuntimeSearchParam next : jpaSearchParams) {
if (!haveSeen.add(next.getId().toUnqualifiedVersionless().getValue())) { if (next.getId() != null && !haveSeen.add(next.getId().toUnqualifiedVersionless().getValue())) {
continue; continue;
} }
Set<String> paramNames = new HashSet<>(); Set<String> paramNames = new TreeSet<>();
for (JpaRuntimeSearchParam.Component nextComponent : next.getComponents()) { for (RuntimeSearchParam.Component nextComponent : next.getComponents()) {
String nextRef = nextComponent.getReference().getReferenceElement().toUnqualifiedVersionless().getValue(); String nextRef = nextComponent.getReference();
RuntimeSearchParam componentTarget = idToRuntimeSearchParam.get(nextRef); RuntimeSearchParam componentTarget = idToRuntimeSearchParam.get(nextRef);
if (componentTarget != null) { if (componentTarget != null) {
next.getCompositeOf().add(componentTarget);
paramNames.add(componentTarget.getName()); paramNames.add(componentTarget.getName());
} else { } else {
String existingParams = idToRuntimeSearchParam String message = "Search parameter " + next + " refers to unknown component " + nextRef + ", ignoring this parameter";
.keySet()
.stream()
.sorted()
.collect(Collectors.joining(", "));
String message = "Search parameter " + next.getId().toUnqualifiedVersionless().getValue() + " refers to unknown component " + nextRef + ", ignoring this parameter (valid values: " + existingParams + ")";
ourLog.warn(message); ourLog.warn(message);
// Interceptor broadcast: JPA_PERFTRACE_WARNING // Interceptor broadcast: JPA_PERFTRACE_WARNING
@ -141,8 +137,7 @@ public class JpaSearchParamCache {
} }
} }
if (next.getCompositeOf() != null) { if (next.isUnique()) {
next.getCompositeOf().sort((theO1, theO2) -> StringUtils.compare(theO1.getName(), theO2.getName()));
for (String nextBase : next.getBase()) { for (String nextBase : next.getBase()) {
activeParamNamesToUniqueSearchParams.computeIfAbsent(nextBase, v -> new HashMap<>()); activeParamNamesToUniqueSearchParams.computeIfAbsent(nextBase, v -> new HashMap<>());
activeParamNamesToUniqueSearchParams.get(nextBase).computeIfAbsent(paramNames, t -> new ArrayList<>()); activeParamNamesToUniqueSearchParams.get(nextBase).computeIfAbsent(paramNames, t -> new ArrayList<>());

View File

@ -23,30 +23,53 @@ package ca.uhn.fhir.jpa.searchparam.registry;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.rest.api.Constants;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Stream; import java.util.stream.Stream;
public class ReadOnlySearchParamCache { public class ReadOnlySearchParamCache {
private static final Logger ourLog = LoggerFactory.getLogger(ReadOnlySearchParamCache.class);
// resourceName -> searchParamName -> searchparam
protected final Map<String, Map<String, RuntimeSearchParam>> myMap;
// resourceName -> searchParamName -> searchparam
protected final Map<String, Map<String, RuntimeSearchParam>> myResourceNameToSpNameToSp;
protected final Map<String, RuntimeSearchParam> myUrlToParam;
/**
* Constructor
*/
ReadOnlySearchParamCache() { ReadOnlySearchParamCache() {
myMap = new HashMap<>(); myResourceNameToSpNameToSp = new HashMap<>();
myUrlToParam = new HashMap<>();
} }
/**
* Copy constructor
*/
private ReadOnlySearchParamCache(RuntimeSearchParamCache theRuntimeSearchParamCache) { private ReadOnlySearchParamCache(RuntimeSearchParamCache theRuntimeSearchParamCache) {
myMap = theRuntimeSearchParamCache.myMap; myResourceNameToSpNameToSp = theRuntimeSearchParamCache.myResourceNameToSpNameToSp;
myUrlToParam = theRuntimeSearchParamCache.myUrlToParam;
}
public Stream<RuntimeSearchParam> getSearchParamStream() {
return myResourceNameToSpNameToSp.values().stream().flatMap(entry -> entry.values().stream());
}
protected Map<String, RuntimeSearchParam> getSearchParamMap(String theResourceName) {
Map<String, RuntimeSearchParam> retval = myResourceNameToSpNameToSp.get(theResourceName);
if (retval == null) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(myResourceNameToSpNameToSp.get(theResourceName));
}
public int size() {
return myResourceNameToSpNameToSp.size();
}
public RuntimeSearchParam getByUrl(String theUrl) {
return myUrlToParam.get(theUrl);
} }
public static ReadOnlySearchParamCache fromFhirContext(FhirContext theFhirContext) { public static ReadOnlySearchParamCache fromFhirContext(FhirContext theFhirContext) {
@ -58,7 +81,7 @@ public class ReadOnlySearchParamCache {
RuntimeResourceDefinition nextResDef = theFhirContext.getResourceDefinition(resourceName); RuntimeResourceDefinition nextResDef = theFhirContext.getResourceDefinition(resourceName);
String nextResourceName = nextResDef.getName(); String nextResourceName = nextResDef.getName();
HashMap<String, RuntimeSearchParam> nameToParam = new HashMap<>(); HashMap<String, RuntimeSearchParam> nameToParam = new HashMap<>();
retval.myMap.put(nextResourceName, nameToParam); retval.myResourceNameToSpNameToSp.put(nextResourceName, nameToParam);
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) { for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
nameToParam.put(nextSp.getName(), nextSp); nameToParam.put(nextSp.getName(), nextSp);
@ -70,33 +93,4 @@ public class ReadOnlySearchParamCache {
public static ReadOnlySearchParamCache fromRuntimeSearchParamCache(RuntimeSearchParamCache theRuntimeSearchParamCache) { public static ReadOnlySearchParamCache fromRuntimeSearchParamCache(RuntimeSearchParamCache theRuntimeSearchParamCache) {
return new ReadOnlySearchParamCache(theRuntimeSearchParamCache); return new ReadOnlySearchParamCache(theRuntimeSearchParamCache);
} }
public Stream<RuntimeSearchParam> getSearchParamStream() {
return myMap.values().stream().flatMap(entry -> entry.values().stream());
}
protected Map<String, RuntimeSearchParam> getSearchParamMap(String theResourceName) {
Map<String, RuntimeSearchParam> retval = myMap.get(theResourceName);
if (retval == null) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(myMap.get(theResourceName));
}
public Collection<String> getValidSearchParameterNamesIncludingMeta(String theResourceName) {
TreeSet<String> retval;
Map<String, RuntimeSearchParam> searchParamMap = myMap.get(theResourceName);
if (searchParamMap == null) {
retval = new TreeSet<>();
} else {
retval = new TreeSet<>(searchParamMap.keySet());
}
retval.add(IAnyResource.SP_RES_ID);
retval.add(Constants.PARAM_LASTUPDATED);
return retval;
}
public int size() {
return myMap.size();
}
} }

View File

@ -28,35 +28,42 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class RuntimeSearchParamCache extends ReadOnlySearchParamCache { public class RuntimeSearchParamCache extends ReadOnlySearchParamCache {
private static final Logger ourLog = LoggerFactory.getLogger(RuntimeSearchParamCache.class); private static final Logger ourLog = LoggerFactory.getLogger(RuntimeSearchParamCache.class);
protected RuntimeSearchParamCache() { protected RuntimeSearchParamCache() {
} }
public static RuntimeSearchParamCache fromReadOnlySearchParmCache(ReadOnlySearchParamCache theBuiltInSearchParams) {
RuntimeSearchParamCache retval = new RuntimeSearchParamCache();
retval.putAll(theBuiltInSearchParams);
return retval;
}
public void add(String theResourceName, String theName, RuntimeSearchParam theSearchParam) { public void add(String theResourceName, String theName, RuntimeSearchParam theSearchParam) {
getSearchParamMap(theResourceName).put(theName, theSearchParam); getSearchParamMap(theResourceName).put(theName, theSearchParam);
String uri = theSearchParam.getUri();
if (isNotBlank(uri)) {
if (myUrlToParam.containsKey(uri)) {
ourLog.warn("Multiple search parameters have URL: {}", uri);
}
myUrlToParam.put(uri, theSearchParam);
}
if (theSearchParam.getId() != null && theSearchParam.getId().hasIdPart()) {
String value = theSearchParam.getId().toUnqualifiedVersionless().getValue();
myUrlToParam.put(value, theSearchParam);
}
} }
public void remove(String theResourceName, String theName) { public void remove(String theResourceName, String theName) {
if (!myMap.containsKey(theResourceName)) { if (!myResourceNameToSpNameToSp.containsKey(theResourceName)) {
return; return;
} }
myMap.get(theResourceName).remove(theName); myResourceNameToSpNameToSp.get(theResourceName).remove(theName);
} }
private void putAll(ReadOnlySearchParamCache theReadOnlySearchParamCache) { private void putAll(ReadOnlySearchParamCache theReadOnlySearchParamCache) {
Set<Map.Entry<String, Map<String, RuntimeSearchParam>>> builtInSps = theReadOnlySearchParamCache.myMap.entrySet(); Set<Map.Entry<String, Map<String, RuntimeSearchParam>>> builtInSps = theReadOnlySearchParamCache.myResourceNameToSpNameToSp.entrySet();
for (Map.Entry<String, Map<String, RuntimeSearchParam>> nextBuiltInEntry : builtInSps) { for (Map.Entry<String, Map<String, RuntimeSearchParam>> nextBuiltInEntry : builtInSps) {
for (RuntimeSearchParam nextParam : nextBuiltInEntry.getValue().values()) { for (RuntimeSearchParam nextParam : nextBuiltInEntry.getValue().values()) {
String nextResourceName = nextBuiltInEntry.getKey(); String nextResourceName = nextBuiltInEntry.getKey();
getSearchParamMap(nextResourceName).put(nextParam.getName(), nextParam); add(nextResourceName, nextParam.getName(), nextParam);
} }
ourLog.trace("Have {} built-in SPs for: {}", nextBuiltInEntry.getValue().size(), nextBuiltInEntry.getKey()); ourLog.trace("Have {} built-in SPs for: {}", nextBuiltInEntry.getValue().size(), nextBuiltInEntry.getKey());
@ -65,7 +72,7 @@ public class RuntimeSearchParamCache extends ReadOnlySearchParamCache {
public RuntimeSearchParam get(String theResourceName, String theParamName) { public RuntimeSearchParam get(String theResourceName, String theParamName) {
RuntimeSearchParam retVal = null; RuntimeSearchParam retVal = null;
Map<String, RuntimeSearchParam> params = myMap.get(theResourceName); Map<String, RuntimeSearchParam> params = myResourceNameToSpNameToSp.get(theResourceName);
if (params != null) { if (params != null) {
retVal = params.get(theParamName); retVal = params.get(theParamName);
} }
@ -73,11 +80,17 @@ public class RuntimeSearchParamCache extends ReadOnlySearchParamCache {
} }
public Set<String> getResourceNameKeys() { public Set<String> getResourceNameKeys() {
return myMap.keySet(); return myResourceNameToSpNameToSp.keySet();
} }
@Override @Override
protected Map<String, RuntimeSearchParam> getSearchParamMap(String theResourceName) { protected Map<String, RuntimeSearchParam> getSearchParamMap(String theResourceName) {
return myMap.computeIfAbsent(theResourceName, k -> new HashMap<>()); return myResourceNameToSpNameToSp.computeIfAbsent(theResourceName, k -> new HashMap<>());
}
public static RuntimeSearchParamCache fromReadOnlySearchParmCache(ReadOnlySearchParamCache theBuiltInSearchParams) {
RuntimeSearchParamCache retval = new RuntimeSearchParamCache();
retval.putAll(theBuiltInSearchParams);
return retval;
} }
} }

View File

@ -21,7 +21,6 @@ package ca.uhn.fhir.jpa.searchparam.registry;
*/ */
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder; import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
import ca.uhn.fhir.interceptor.api.IInterceptorService; import ca.uhn.fhir.interceptor.api.IInterceptorService;
@ -31,10 +30,10 @@ import ca.uhn.fhir.jpa.cache.IResourceChangeListenerCache;
import ca.uhn.fhir.jpa.cache.IResourceChangeListenerRegistry; import ca.uhn.fhir.jpa.cache.IResourceChangeListenerRegistry;
import ca.uhn.fhir.jpa.cache.ResourceChangeResult; import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.SearchParameterUtil; import ca.uhn.fhir.util.SearchParameterUtil;
import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.StopWatch;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -46,6 +45,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Nullable;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
@ -58,11 +58,13 @@ import java.util.Set;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
public class SearchParamRegistryImpl implements ISearchParamRegistry, IResourceChangeListener { public class SearchParamRegistryImpl implements ISearchParamRegistry, IResourceChangeListener, ISearchParamRegistryController {
// TODO: JA remove unused?
private static final Logger ourLog = LoggerFactory.getLogger(SearchParamRegistryImpl.class); private static final Logger ourLog = LoggerFactory.getLogger(SearchParamRegistryImpl.class);
private static final int MAX_MANAGED_PARAM_COUNT = 10000; private static final int MAX_MANAGED_PARAM_COUNT = 10000;
private static final long REFRESH_INTERVAL = DateUtils.MILLIS_PER_HOUR; private static final long REFRESH_INTERVAL = DateUtils.MILLIS_PER_HOUR;
private final JpaSearchParamCache myJpaSearchParamCache = new JpaSearchParamCache();
@Autowired @Autowired
private ModelConfig myModelConfig; private ModelConfig myModelConfig;
@Autowired @Autowired
@ -73,10 +75,8 @@ public class SearchParamRegistryImpl implements ISearchParamRegistry, IResourceC
private SearchParameterCanonicalizer mySearchParameterCanonicalizer; private SearchParameterCanonicalizer mySearchParameterCanonicalizer;
@Autowired @Autowired
private IResourceChangeListenerRegistry myResourceChangeListenerRegistry; private IResourceChangeListenerRegistry myResourceChangeListenerRegistry;
private volatile ReadOnlySearchParamCache myBuiltInSearchParams; private volatile ReadOnlySearchParamCache myBuiltInSearchParams;
private volatile IPhoneticEncoder myPhoneticEncoder; private volatile IPhoneticEncoder myPhoneticEncoder;
private final JpaSearchParamCache myJpaSearchParamCache = new JpaSearchParamCache();
private volatile RuntimeSearchParamCache myActiveSearchParams; private volatile RuntimeSearchParamCache myActiveSearchParams;
@Autowired @Autowired
@ -109,15 +109,25 @@ public class SearchParamRegistryImpl implements ISearchParamRegistry, IResourceC
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
return myJpaSearchParamCache.getActiveUniqueSearchParams(theResourceName); return myJpaSearchParamCache.getActiveUniqueSearchParams(theResourceName);
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
return myJpaSearchParamCache.getActiveUniqueSearchParams(theResourceName, theParamNames); return myJpaSearchParamCache.getActiveUniqueSearchParams(theResourceName, theParamNames);
} }
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
if (myActiveSearchParams != null) {
return myActiveSearchParams.getByUrl(theUrl);
} else {
return null;
}
}
private void rebuildActiveSearchParams() { private void rebuildActiveSearchParams() {
ourLog.info("Rebuilding SearchParamRegistry"); ourLog.info("Rebuilding SearchParamRegistry");
SearchParameterMap params = new SearchParameterMap(); SearchParameterMap params = new SearchParameterMap();
@ -205,26 +215,14 @@ public class SearchParamRegistryImpl implements ISearchParamRegistry, IResourceC
continue; continue;
} }
Map<String, RuntimeSearchParam> searchParamMap = theSearchParams.getSearchParamMap(nextBaseName);
String name = runtimeSp.getName(); String name = runtimeSp.getName();
theSearchParams.add(nextBaseName, name, runtimeSp);
ourLog.debug("Adding search parameter {}.{} to SearchParamRegistry", nextBaseName, StringUtils.defaultString(name, "[composite]")); ourLog.debug("Adding search parameter {}.{} to SearchParamRegistry", nextBaseName, StringUtils.defaultString(name, "[composite]"));
searchParamMap.put(name, runtimeSp);
retval++; retval++;
} }
return retval; return retval;
} }
@Override
public RuntimeSearchParam getSearchParamByName(RuntimeResourceDefinition theResourceDef, String theParamName) {
Map<String, RuntimeSearchParam> params = getActiveSearchParams(theResourceDef.getName());
return params.get(theParamName);
}
@Override
public Collection<RuntimeSearchParam> getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef) {
return getActiveSearchParams(theResourceDef.getName()).values();
}
@Override @Override
public void requestRefresh() { public void requestRefresh() {
myResourceChangeListenerCache.requestRefresh(); myResourceChangeListenerCache.requestRefresh();
@ -255,7 +253,6 @@ public class SearchParamRegistryImpl implements ISearchParamRegistry, IResourceC
myResourceChangeListenerRegistry.unregisterResourceResourceChangeListener(this); myResourceChangeListenerRegistry.unregisterResourceResourceChangeListener(this);
} }
@Override
public ReadOnlySearchParamCache getActiveSearchParams() { public ReadOnlySearchParamCache getActiveSearchParams() {
requiresActiveSearchParams(); requiresActiveSearchParams();
if (myActiveSearchParams == null) { if (myActiveSearchParams == null) {

View File

@ -23,12 +23,10 @@ package ca.uhn.fhir.jpa.searchparam.registry;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam; import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.context.phonetic.PhoneticEncoderEnum; import ca.uhn.fhir.context.phonetic.PhoneticEncoderEnum;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.model.api.ExtensionDt; import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.DatatypeUtil; import ca.uhn.fhir.util.DatatypeUtil;
import ca.uhn.fhir.util.ExtensionUtil;
import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.FhirTerser;
import ca.uhn.fhir.util.HapiExtensions; import ca.uhn.fhir.util.HapiExtensions;
import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.EnumUtils;
@ -41,7 +39,6 @@ import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.Reference;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -57,6 +54,7 @@ import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.startsWith;
@Service @Service
public class SearchParameterCanonicalizer { public class SearchParameterCanonicalizer {
@ -70,7 +68,7 @@ public class SearchParameterCanonicalizer {
} }
protected RuntimeSearchParam canonicalizeSearchParameter(IBaseResource theSearchParameter) { protected RuntimeSearchParam canonicalizeSearchParameter(IBaseResource theSearchParameter) {
JpaRuntimeSearchParam retVal; RuntimeSearchParam retVal;
switch (myFhirContext.getVersion().getVersion()) { switch (myFhirContext.getVersion().getVersion()) {
case DSTU2: case DSTU2:
retVal = canonicalizeSearchParameterDstu2((ca.uhn.fhir.model.dstu2.resource.SearchParameter) theSearchParameter); retVal = canonicalizeSearchParameterDstu2((ca.uhn.fhir.model.dstu2.resource.SearchParameter) theSearchParameter);
@ -92,7 +90,7 @@ public class SearchParameterCanonicalizer {
return retVal; return retVal;
} }
private JpaRuntimeSearchParam canonicalizeSearchParameterDstu2(ca.uhn.fhir.model.dstu2.resource.SearchParameter theNextSp) { private RuntimeSearchParam canonicalizeSearchParameterDstu2(ca.uhn.fhir.model.dstu2.resource.SearchParameter theNextSp) {
String name = theNextSp.getCode(); String name = theNextSp.getCode();
String description = theNextSp.getDescription(); String description = theNextSp.getDescription();
String path = theNextSp.getXpath(); String path = theNextSp.getXpath();
@ -162,12 +160,12 @@ public class SearchParameterCanonicalizer {
} }
} }
List<JpaRuntimeSearchParam.Component> components = Collections.emptyList(); List<RuntimeSearchParam.Component> components = Collections.emptyList();
Collection<? extends IPrimitiveType<String>> base = Collections.singletonList(theNextSp.getBaseElement()); Collection<? extends IPrimitiveType<String>> base = Collections.singletonList(theNextSp.getBaseElement());
return new JpaRuntimeSearchParam(id, uri, name, description, path, paramType, providesMembershipInCompartments, targets, status, unique, components, toStrings(base)); return new RuntimeSearchParam(id, uri, name, description, path, paramType, providesMembershipInCompartments, targets, status, unique, components, toStrings(base));
} }
private JpaRuntimeSearchParam canonicalizeSearchParameterDstu3(org.hl7.fhir.dstu3.model.SearchParameter theNextSp) { private RuntimeSearchParam canonicalizeSearchParameterDstu3(org.hl7.fhir.dstu3.model.SearchParameter theNextSp) {
String name = theNextSp.getCode(); String name = theNextSp.getCode();
String description = theNextSp.getDescription(); String description = theNextSp.getDescription();
String path = theNextSp.getExpression(); String path = theNextSp.getExpression();
@ -242,15 +240,15 @@ public class SearchParameterCanonicalizer {
} }
} }
List<JpaRuntimeSearchParam.Component> components = new ArrayList<>(); List<RuntimeSearchParam.Component> components = new ArrayList<>();
for (SearchParameter.SearchParameterComponentComponent next : theNextSp.getComponent()) { for (SearchParameter.SearchParameterComponentComponent next : theNextSp.getComponent()) {
components.add(new JpaRuntimeSearchParam.Component(next.getExpression(), next.getDefinition())); components.add(new RuntimeSearchParam.Component(next.getExpression(), next.getDefinition().getReferenceElement().toUnqualifiedVersionless().getValue()));
} }
return new JpaRuntimeSearchParam(id, uri, name, description, path, paramType, providesMembershipInCompartments, targets, status, unique, components, toStrings(theNextSp.getBase())); return new RuntimeSearchParam(id, uri, name, description, path, paramType, providesMembershipInCompartments, targets, status, unique, components, toStrings(theNextSp.getBase()));
} }
private JpaRuntimeSearchParam canonicalizeSearchParameterR4Plus(IBaseResource theNextSp) { private RuntimeSearchParam canonicalizeSearchParameterR4Plus(IBaseResource theNextSp) {
FhirTerser terser = myFhirContext.newTerser(); FhirTerser terser = myFhirContext.newTerser();
String name = terser.getSinglePrimitiveValueOrNull(theNextSp, "code"); String name = terser.getSinglePrimitiveValueOrNull(theNextSp, "code");
String description = terser.getSinglePrimitiveValueOrNull(theNextSp, "description"); String description = terser.getSinglePrimitiveValueOrNull(theNextSp, "description");
@ -318,30 +316,34 @@ public class SearchParameterCanonicalizer {
String value = ((IBaseHasExtensions) theNextSp).getExtension() String value = ((IBaseHasExtensions) theNextSp).getExtension()
.stream() .stream()
.filter(e -> HapiExtensions.EXT_SP_UNIQUE.equals(e.getUrl())) .filter(e -> HapiExtensions.EXT_SP_UNIQUE.equals(e.getUrl()))
.filter(t->t.getValue() instanceof IPrimitiveType) .filter(t -> t.getValue() instanceof IPrimitiveType)
.map(t->(IPrimitiveType<?>)t.getValue()) .map(t -> (IPrimitiveType<?>) t.getValue())
.map(t->t.getValueAsString()) .map(t -> t.getValueAsString())
.findFirst() .findFirst()
.orElse(""); .orElse("");
if ("true".equalsIgnoreCase(value)) { if ("true".equalsIgnoreCase(value)) {
unique = true; unique = true;
} }
List<JpaRuntimeSearchParam.Component> components = new ArrayList<>(); List<RuntimeSearchParam.Component> components = new ArrayList<>();
for (IBase next : terser.getValues(theNextSp, "component")) { for (IBase next : terser.getValues(theNextSp, "component")) {
String expression = terser.getSinglePrimitiveValueOrNull(next, "expression"); String expression = terser.getSinglePrimitiveValueOrNull(next, "expression");
String definition = terser.getSinglePrimitiveValueOrNull(next, "definition"); String definition = terser.getSinglePrimitiveValueOrNull(next, "definition");
components.add(new JpaRuntimeSearchParam.Component(expression, new Reference(definition))); if (startsWith(definition, "/SearchParameter/")) {
definition = definition.substring(1);
}
components.add(new RuntimeSearchParam.Component(expression, definition));
} }
return new JpaRuntimeSearchParam(id, uri, name, description, path, paramType, providesMembershipInCompartments, targets, status, unique, components, base); return new RuntimeSearchParam(id, uri, name, description, path, paramType, providesMembershipInCompartments, targets, status, unique, components, base);
} }
/** /**
* Extracts any extensions from the resource and populates an extension field in the * Extracts any extensions from the resource and populates an extension field in the
*/ */
protected void extractExtensions(IBaseResource theSearchParamResource, JpaRuntimeSearchParam theRuntimeSearchParam) { protected void extractExtensions(IBaseResource theSearchParamResource, RuntimeSearchParam theRuntimeSearchParam) {
if (theSearchParamResource instanceof IBaseHasExtensions) { if (theSearchParamResource instanceof IBaseHasExtensions) {
List<? extends IBaseExtension<?, ?>> extensions = ((IBaseHasExtensions) theSearchParamResource).getExtension(); List<? extends IBaseExtension<?, ?>> extensions = ((IBaseHasExtensions) theSearchParamResource).getExtension();
for (IBaseExtension<?, ?> next : extensions) { for (IBaseExtension<?, ?> next : extensions) {
@ -356,7 +358,7 @@ public class SearchParameterCanonicalizer {
} }
} }
private void setEncoder(JpaRuntimeSearchParam theRuntimeSearchParam, IBaseDatatype theValue) { private void setEncoder(RuntimeSearchParam theRuntimeSearchParam, IBaseDatatype theValue) {
if (theValue instanceof IPrimitiveType) { if (theValue instanceof IPrimitiveType) {
String stringValue = ((IPrimitiveType<?>) theValue).getValueAsString(); String stringValue = ((IPrimitiveType<?>) theValue).getValueAsString();
PhoneticEncoderEnum encoderEnum = EnumUtils.getEnum(PhoneticEncoderEnum.class, stringValue); PhoneticEncoderEnum encoderEnum = EnumUtils.getEnum(PhoneticEncoderEnum.class, stringValue);

View File

@ -0,0 +1,194 @@
package ca.uhn.fhir.jpa.searchparam.util;
/*-
* #%L
* HAPI FHIR Search Parameters
* %%
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.CompositeAndListParam;
import ca.uhn.fhir.rest.param.DateAndListParam;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.HasAndListParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.NumberAndListParam;
import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.QuantityAndListParam;
import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.SpecialAndListParam;
import ca.uhn.fhir.rest.param.SpecialParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.UriAndListParam;
import ca.uhn.fhir.rest.param.UriParam;
import ca.uhn.fhir.rest.param.binder.QueryParameterAndBinder;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public enum JpaParamUtil {
;
/**
* This is a utility method intended provided to help the JPA module.
*/
public static IQueryParameterAnd<?> parseQueryParams(FhirContext theContext, RestSearchParameterTypeEnum paramType,
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
QueryParameterAndBinder binder;
switch (paramType) {
case COMPOSITE:
throw new UnsupportedOperationException();
case DATE:
binder = new QueryParameterAndBinder(DateAndListParam.class,
Collections.emptyList());
break;
case NUMBER:
binder = new QueryParameterAndBinder(NumberAndListParam.class,
Collections.emptyList());
break;
case QUANTITY:
binder = new QueryParameterAndBinder(QuantityAndListParam.class,
Collections.emptyList());
break;
case REFERENCE:
binder = new QueryParameterAndBinder(ReferenceAndListParam.class,
Collections.emptyList());
break;
case STRING:
binder = new QueryParameterAndBinder(StringAndListParam.class,
Collections.emptyList());
break;
case TOKEN:
binder = new QueryParameterAndBinder(TokenAndListParam.class,
Collections.emptyList());
break;
case URI:
binder = new QueryParameterAndBinder(UriAndListParam.class,
Collections.emptyList());
break;
case HAS:
binder = new QueryParameterAndBinder(HasAndListParam.class,
Collections.emptyList());
break;
case SPECIAL:
binder = new QueryParameterAndBinder(SpecialAndListParam.class,
Collections.emptyList());
break;
default:
throw new IllegalArgumentException("Parameter '" + theUnqualifiedParamName + "' has type " + paramType + " which is currently not supported.");
}
return binder.parse(theContext, theUnqualifiedParamName, theParameters);
}
/**
* This is a utility method intended provided to help the JPA module.
*/
public static IQueryParameterAnd<?> parseQueryParams(ISearchParamRegistry theSearchParamRegistry, FhirContext theContext, RuntimeSearchParam theParamDef,
String theUnqualifiedParamName, List<QualifiedParamList> theParameters) {
RestSearchParameterTypeEnum paramType = theParamDef.getParamType();
if (paramType == RestSearchParameterTypeEnum.COMPOSITE) {
List<RuntimeSearchParam> compositeList = resolveComponentParameters(theSearchParamRegistry, theParamDef);
if (compositeList.size() != 2) {
throw new ConfigurationException("Search parameter of type " + theUnqualifiedParamName
+ " must have 2 composite types declared in parameter annotation, found "
+ compositeList.size());
}
RuntimeSearchParam left = compositeList.get(0);
RuntimeSearchParam right = compositeList.get(1);
@SuppressWarnings({"unchecked", "rawtypes"})
CompositeAndListParam<IQueryParameterType, IQueryParameterType> cp = new CompositeAndListParam(
getCompositeBindingClass(left.getParamType(), left.getName()),
getCompositeBindingClass(right.getParamType(), right.getName()));
cp.setValuesAsQueryTokens(theContext, theUnqualifiedParamName, theParameters);
return cp;
} else {
return parseQueryParams(theContext, paramType, theUnqualifiedParamName, theParameters);
}
}
public static List<RuntimeSearchParam> resolveComponentParameters(ISearchParamRegistry theSearchParamRegistry, RuntimeSearchParam theParamDef) {
List<RuntimeSearchParam> compositeList = new ArrayList<>();
List<RuntimeSearchParam.Component> components = theParamDef.getComponents();
for (RuntimeSearchParam.Component next : components) {
String url = next.getReference();
RuntimeSearchParam componentParam = theSearchParamRegistry.getActiveSearchParamByUrl(url);
if (componentParam == null) {
throw new InternalErrorException("Can not find SearchParameter: " + url);
}
compositeList.add(componentParam);
}
compositeList.sort((Comparator.comparing(RuntimeSearchParam::getName)));
return compositeList;
}
private static Class<?> getCompositeBindingClass(RestSearchParameterTypeEnum paramType,
String theUnqualifiedParamName) {
switch (paramType) {
case DATE:
return DateParam.class;
case NUMBER:
return NumberParam.class;
case QUANTITY:
return QuantityParam.class;
case REFERENCE:
return ReferenceParam.class;
case STRING:
return StringParam.class;
case TOKEN:
return TokenParam.class;
case URI:
return UriParam.class;
case HAS:
return HasParam.class;
case SPECIAL:
return SpecialParam.class;
case COMPOSITE:
default:
throw new IllegalArgumentException("Parameter '" + theUnqualifiedParamName + "' has type " + paramType
+ " which is currently not supported.");
}
}
}

View File

@ -7,7 +7,7 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3; import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorDstu3;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.StopWatch;
import org.hl7.fhir.dstu3.model.Patient; import org.hl7.fhir.dstu3.model.Patient;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -16,11 +16,11 @@ import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamQuantity;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants; import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistryController;
import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache; import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.StringUtil; import ca.uhn.fhir.util.StringUtil;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -34,9 +34,9 @@ import org.hl7.fhir.dstu3.model.Questionnaire;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import javax.annotation.Nullable;
import java.text.Normalizer; import java.text.Normalizer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -132,11 +132,11 @@ public class SearchParamExtractorDstu3Test {
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry); SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
extractor.start(); extractor.start();
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
extractor.extractSearchParamStrings(resource); extractor.extractSearchParamStrings(resource);
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", null, RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", null, RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
extractor.extractSearchParamStrings(resource); extractor.extractSearchParamStrings(resource);
} }
@ -148,7 +148,7 @@ public class SearchParamExtractorDstu3Test {
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry); SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), new PartitionSettings(), ourCtx, searchParamRegistry);
extractor.start(); extractor.start();
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "communication.language.coding.system | communication.language.coding.code", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "communication.language.coding.system | communication.language.coding.code", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
resource.getCommunicationFirstRep().getLanguage().getCodingFirstRep().setCode("blah"); resource.getCommunicationFirstRep().getLanguage().getCodingFirstRep().setCode("blah");
Set<ResourceIndexedSearchParamString> strings = extractor.extractSearchParamStrings(resource); Set<ResourceIndexedSearchParamString> strings = extractor.extractSearchParamStrings(resource);
@ -166,37 +166,37 @@ public class SearchParamExtractorDstu3Test {
extractor.start(); extractor.start();
{ {
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> outcome = extractor.extractSearchParamStrings(resource); ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> outcome = extractor.extractSearchParamStrings(resource);
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient")); assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
} }
{ {
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.TOKEN, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.TOKEN, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> outcome = extractor.extractSearchParamTokens(resource); ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> outcome = extractor.extractSearchParamTokens(resource);
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient")); assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
} }
{ {
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.QUANTITY, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.QUANTITY, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> outcome = extractor.extractSearchParamQuantity(resource); ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> outcome = extractor.extractSearchParamQuantity(resource);
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient")); assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
} }
{ {
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.DATE, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.DATE, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> outcome = extractor.extractSearchParamDates(resource); ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> outcome = extractor.extractSearchParamDates(resource);
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient")); assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
} }
{ {
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.NUMBER, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.NUMBER, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> outcome = extractor.extractSearchParamNumber(resource); ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> outcome = extractor.extractSearchParamNumber(resource);
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient")); assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
} }
{ {
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.URI, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE)); searchParamRegistry.addSearchParam(new RuntimeSearchParam(null, null, "foo", "foo", "Patient", RestSearchParameterTypeEnum.URI, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
Patient resource = new Patient(); Patient resource = new Patient();
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> outcome = extractor.extractSearchParamUri(resource); ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> outcome = extractor.extractSearchParamUri(resource);
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient")); assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
@ -222,7 +222,9 @@ public class SearchParamExtractorDstu3Test {
assertEquals(longitude, coord.getLongitude(), 0.0); assertEquals(longitude, coord.getLongitude(), 0.0);
} }
private static class MySearchParamRegistry implements ISearchParamRegistry { private static class MySearchParamRegistry implements ISearchParamRegistry, ISearchParamRegistryController {
// TODO: JA remove unused?
private final List<RuntimeSearchParam> myAddedSearchParams = new ArrayList<>(); private final List<RuntimeSearchParam> myAddedSearchParams = new ArrayList<>();
@ -249,7 +251,6 @@ public class SearchParamExtractorDstu3Test {
return new ResourceChangeResult(); return new ResourceChangeResult();
} }
@Override
public ReadOnlySearchParamCache getActiveSearchParams() { public ReadOnlySearchParamCache getActiveSearchParams() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -268,12 +269,18 @@ public class SearchParamExtractorDstu3Test {
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -282,16 +289,6 @@ public class SearchParamExtractorDstu3Test {
// nothing // nothing
} }
@Override
public RuntimeSearchParam getSearchParamByName(RuntimeResourceDefinition theResourceDef, String theParamName) {
return null;
}
@Override
public Collection<RuntimeSearchParam> getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef) {
return null;
}
@Override @Override
public void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) { public void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {
// nothing // nothing

View File

@ -20,9 +20,9 @@ import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
import ca.uhn.fhir.jpa.cache.ResourceChangeResult; import ca.uhn.fhir.jpa.cache.ResourceChangeResult;
import ca.uhn.fhir.jpa.model.config.PartitionSettings; import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.model.entity.ModelConfig; import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam; import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistryController;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache; import ca.uhn.fhir.jpa.searchparam.registry.ReadOnlySearchParamCache;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseEnumeration; import org.hl7.fhir.instance.model.api.IBaseEnumeration;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
@ -32,8 +32,8 @@ import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -45,6 +45,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
// TODO JA Please fix this test. Expanding FhirContext.getResourceTypes() to cover all resource types broke this test. // TODO JA Please fix this test. Expanding FhirContext.getResourceTypes() to cover all resource types broke this test.
@Disabled @Disabled
public class SearchParamExtractorMegaTest { public class SearchParamExtractorMegaTest {
// TODO: JA remove unused?
private static final Logger ourLog = LoggerFactory.getLogger(SearchParamExtractorMegaTest.class); private static final Logger ourLog = LoggerFactory.getLogger(SearchParamExtractorMegaTest.class);
@ -231,7 +232,7 @@ public class SearchParamExtractorMegaTest {
} }
private static class MySearchParamRegistry implements ISearchParamRegistry { private static class MySearchParamRegistry implements ISearchParamRegistry, ISearchParamRegistryController {
private final FhirContext myCtx; private final FhirContext myCtx;
private List<RuntimeSearchParam> myAddedSearchParams = new ArrayList<>(); private List<RuntimeSearchParam> myAddedSearchParams = new ArrayList<>();
@ -263,7 +264,6 @@ public class SearchParamExtractorMegaTest {
return new ResourceChangeResult(); return new ResourceChangeResult();
} }
@Override
public ReadOnlySearchParamCache getActiveSearchParams() { public ReadOnlySearchParamCache getActiveSearchParams() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -282,12 +282,18 @@ public class SearchParamExtractorMegaTest {
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public List<JpaRuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) { public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -296,16 +302,6 @@ public class SearchParamExtractorMegaTest {
// nothing // nothing
} }
@Override
public RuntimeSearchParam getSearchParamByName(RuntimeResourceDefinition theResourceDef, String theParamName) {
return null;
}
@Override
public Collection<RuntimeSearchParam> getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef) {
return null;
}
@Override @Override
public void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) { public void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {
// nothing // nothing

View File

@ -7,12 +7,12 @@ import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate; import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams; import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.model.primitive.BaseDateTimeDt; import ca.uhn.fhir.model.primitive.BaseDateTimeDt;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum; import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.rest.param.TokenParamModifier; import ca.uhn.fhir.rest.param.TokenParamModifier;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.r5.model.BaseDateTimeType; import org.hl7.fhir.r5.model.BaseDateTimeType;
import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.DateTimeType; import org.hl7.fhir.r5.model.DateTimeType;
@ -34,8 +34,6 @@ import java.util.Date;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@ -60,16 +58,13 @@ public class InMemoryResourceMatcherR5Test {
@BeforeEach @BeforeEach
public void before() { public void before() {
RuntimeSearchParam dateSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.effective", RestSearchParameterTypeEnum.DATE, null, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE); RuntimeSearchParam dateSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.effective", RestSearchParameterTypeEnum.DATE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
when(mySearchParamRegistry.getSearchParamByName(any(), eq("date"))).thenReturn(dateSearchParam);
when(mySearchParamRegistry.getActiveSearchParam("Observation", "date")).thenReturn(dateSearchParam); when(mySearchParamRegistry.getActiveSearchParam("Observation", "date")).thenReturn(dateSearchParam);
RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.code", RestSearchParameterTypeEnum.TOKEN, null, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE); RuntimeSearchParam codeSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.code", RestSearchParameterTypeEnum.TOKEN, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
when(mySearchParamRegistry.getSearchParamByName(any(), eq("code"))).thenReturn(codeSearchParam);
when(mySearchParamRegistry.getActiveSearchParam("Observation", "code")).thenReturn(codeSearchParam); when(mySearchParamRegistry.getActiveSearchParam("Observation", "code")).thenReturn(codeSearchParam);
RuntimeSearchParam encSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.encounter", RestSearchParameterTypeEnum.REFERENCE, null, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE); RuntimeSearchParam encSearchParam = new RuntimeSearchParam(null, null, null, null, "Observation.encounter", RestSearchParameterTypeEnum.REFERENCE, null, null, RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
when(mySearchParamRegistry.getSearchParamByName(any(), eq("encounter"))).thenReturn(encSearchParam);
when(mySearchParamRegistry.getActiveSearchParam("Observation", "encounter")).thenReturn(encSearchParam); when(mySearchParamRegistry.getActiveSearchParam("Observation", "encounter")).thenReturn(encSearchParam);
myObservation = new Observation(); myObservation = new Observation();

View File

@ -21,6 +21,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.SimpleBundleProvider; import ca.uhn.fhir.rest.server.SimpleBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.Enumerations;
@ -115,7 +116,7 @@ public class SearchParamRegistryImplTest {
} }
@Bean @Bean
ISearchParamRegistry searchParamRegistry() { ISearchParamRegistry searchParamRegistry() {
return new SearchParamRegistryImpl(); return new SearchParamRegistryImpl();
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -28,7 +28,7 @@ import ca.uhn.fhir.jpa.cache.IResourceChangeListenerCache;
import ca.uhn.fhir.jpa.cache.IResourceChangeListenerRegistry; import ca.uhn.fhir.jpa.cache.IResourceChangeListenerRegistry;
import ca.uhn.fhir.jpa.model.sched.ISchedulerService; import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.retry.Retrier; import ca.uhn.fhir.jpa.searchparam.retry.Retrier;
import ca.uhn.fhir.jpa.subscription.match.matcher.subscriber.SubscriptionActivatingSubscriber; import ca.uhn.fhir.jpa.subscription.match.matcher.subscriber.SubscriptionActivatingSubscriber;
import ca.uhn.fhir.rest.api.server.IBundleProvider; import ca.uhn.fhir.rest.api.server.IBundleProvider;

View File

@ -11,7 +11,7 @@ import ca.uhn.fhir.jpa.model.sched.ISchedulerService;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService; import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryResourceMatcher; import ca.uhn.fhir.jpa.searchparam.matcher.InMemoryResourceMatcher;
import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher; import ca.uhn.fhir.jpa.searchparam.matcher.SearchParamMatcher;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig; import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory; import ca.uhn.fhir.jpa.subscription.channel.subscription.SubscriptionChannelFactory;
import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig; import ca.uhn.fhir.jpa.subscription.match.config.SubscriptionProcessorConfig;

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId> <artifactId>hapi-fhir</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -164,7 +164,7 @@
<dependency> <dependency>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-converter</artifactId> <artifactId>hapi-fhir-converter</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -19,7 +19,7 @@ import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4; import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import ca.uhn.fhir.jpa.provider.r5.JpaSystemProviderR5; import ca.uhn.fhir.jpa.provider.r5.JpaSystemProviderR5;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig; import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.EncodingEnum;

View File

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -33,11 +33,9 @@ import ca.uhn.fhir.mdm.rules.json.MdmResourceSearchParamJson;
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson; import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
import ca.uhn.fhir.mdm.rules.json.MdmSimilarityJson; import ca.uhn.fhir.mdm.rules.json.MdmSimilarityJson;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.FhirTerser;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Patient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -54,12 +52,12 @@ public class MdmRuleValidator implements IMdmRuleValidator {
private static final Logger ourLog = LoggerFactory.getLogger(MdmRuleValidator.class); private static final Logger ourLog = LoggerFactory.getLogger(MdmRuleValidator.class);
private final FhirContext myFhirContext; private final FhirContext myFhirContext;
private final ISearchParamRetriever mySearchParamRetriever; private final ISearchParamRegistry mySearchParamRetriever;
private final FhirTerser myTerser; private final FhirTerser myTerser;
private final IFhirPath myFhirPath; private final IFhirPath myFhirPath;
@Autowired @Autowired
public MdmRuleValidator(FhirContext theFhirContext, ISearchParamRetriever theSearchParamRetriever) { public MdmRuleValidator(FhirContext theFhirContext, ISearchParamRegistry theSearchParamRetriever) {
myFhirContext = theFhirContext; myFhirContext = theFhirContext;
myTerser = myFhirContext.newTerser(); myTerser = myFhirContext.newTerser();
if (myFhirContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) { if (myFhirContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {

View File

@ -7,7 +7,7 @@ import ca.uhn.fhir.mdm.rules.config.MdmRuleValidator;
import ca.uhn.fhir.mdm.rules.config.MdmSettings; import ca.uhn.fhir.mdm.rules.config.MdmSettings;
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson; import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc; import ca.uhn.fhir.mdm.rules.svc.MdmResourceMatcherSvc;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
@ -18,7 +18,7 @@ import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public abstract class BaseR4Test { public abstract class BaseR4Test {
protected static final FhirContext ourFhirContext = FhirContext.forR4(); protected static final FhirContext ourFhirContext = FhirContext.forR4();
protected ISearchParamRetriever mySearchParamRetriever = mock(ISearchParamRetriever.class); protected ISearchParamRegistry mySearchParamRetriever = mock(ISearchParamRegistry.class);
protected Patient buildJohn() { protected Patient buildJohn() {
Patient patient = new Patient(); Patient patient = new Patient();

View File

@ -7,15 +7,12 @@ import ca.uhn.fhir.mdm.rules.json.MdmFieldMatchJson;
import ca.uhn.fhir.mdm.rules.json.MdmMatcherJson; import ca.uhn.fhir.mdm.rules.json.MdmMatcherJson;
import ca.uhn.fhir.mdm.rules.json.MdmRulesJson; import ca.uhn.fhir.mdm.rules.json.MdmRulesJson;
import ca.uhn.fhir.mdm.rules.matcher.MdmMatcherEnum; import ca.uhn.fhir.mdm.rules.matcher.MdmMatcherEnum;
import ca.uhn.fhir.util.StopWatch;
import org.hl7.fhir.r4.model.HumanName; import org.hl7.fhir.r4.model.HumanName;
import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;

View File

@ -45,10 +45,7 @@ public class EIDHelperR4Test extends BaseR4Test {
@BeforeEach @BeforeEach
public void before() { public void before() {
when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier")) when(mySearchParamRetriever.getActiveSearchParam("Patient", "identifier"))
.thenReturn(new RuntimeSearchParam( .thenReturn(new RuntimeSearchParam(null, null, "identifier", "Description", "identifier", RestSearchParameterTypeEnum.STRING, new HashSet<>(), new HashSet<>(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null));
"identifier", "Description", "identifier", RestSearchParameterTypeEnum.STRING,
new HashSet<>(), new HashSet<>(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE
));
myMdmSettings = new MdmSettings(new MdmRuleValidator(ourFhirContext, mySearchParamRetriever)) { myMdmSettings = new MdmSettings(new MdmRuleValidator(ourFhirContext, mySearchParamRetriever)) {
{ {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId> <artifactId>hapi-deployable-pom</artifactId>
<version>5.4.0-PRE3-SNAPSHOT</version> <version>5.4.0-PRE4-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath> <relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent> </parent>

View File

@ -28,7 +28,7 @@ import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
import ca.uhn.fhir.rest.server.method.OperationMethodBinding; import ca.uhn.fhir.rest.server.method.OperationMethodBinding;
import ca.uhn.fhir.rest.server.method.SearchMethodBinding; import ca.uhn.fhir.rest.server.method.SearchMethodBinding;
import ca.uhn.fhir.rest.server.method.SearchParameter; import ca.uhn.fhir.rest.server.method.SearchParameter;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.VersionUtil; import ca.uhn.fhir.util.VersionUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
@ -39,6 +39,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -55,7 +56,7 @@ import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
public class RestfulServerConfiguration implements ISearchParamRetriever { public class RestfulServerConfiguration implements ISearchParamRegistry {
private static final Logger ourLog = LoggerFactory.getLogger(RestfulServerConfiguration.class); private static final Logger ourLog = LoggerFactory.getLogger(RestfulServerConfiguration.class);
private Collection<ResourceBinding> resourceBindings; private Collection<ResourceBinding> resourceBindings;
@ -384,6 +385,12 @@ public class RestfulServerConfiguration implements ISearchParamRetriever {
return retVal; return retVal;
} }
@Nullable
@Override
public RuntimeSearchParam getActiveSearchParamByUrl(String theUrl) {
throw new UnsupportedOperationException();
}
private void createRuntimeBinding(Map<String, RuntimeSearchParam> theMapToPopulate, SearchMethodBinding theSearchMethodBinding) { private void createRuntimeBinding(Map<String, RuntimeSearchParam> theMapToPopulate, SearchMethodBinding theSearchMethodBinding) {
List<SearchParameter> parameters = theSearchMethodBinding List<SearchParameter> parameters = theSearchMethodBinding
@ -425,12 +432,11 @@ public class RestfulServerConfiguration implements ISearchParamRetriever {
String description = nextParamDescription; String description = nextParamDescription;
String path = null; String path = null;
RestSearchParameterTypeEnum type = nextParameter.getParamType(); RestSearchParameterTypeEnum type = nextParameter.getParamType();
List<RuntimeSearchParam> compositeOf = Collections.emptyList();
Set<String> providesMembershipInCompartments = Collections.emptySet(); Set<String> providesMembershipInCompartments = Collections.emptySet();
Set<String> targets = Collections.emptySet(); Set<String> targets = Collections.emptySet();
RuntimeSearchParam.RuntimeSearchParamStatusEnum status = RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE; RuntimeSearchParam.RuntimeSearchParamStatusEnum status = RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE;
Collection<String> base = Collections.singletonList(theSearchMethodBinding.getResourceName()); Collection<String> base = Collections.singletonList(theSearchMethodBinding.getResourceName());
RuntimeSearchParam param = new RuntimeSearchParam(id, uri, nextParamName, description, path, type, compositeOf, providesMembershipInCompartments, targets, status, base); RuntimeSearchParam param = new RuntimeSearchParam(id, uri, nextParamName, description, path, type, providesMembershipInCompartments, targets, status, false, null, base);
theMapToPopulate.put(nextParamName, param); theMapToPopulate.put(nextParamName, param);
} }

View File

@ -35,7 +35,7 @@ import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException; import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.method.SearchMethodBinding; import ca.uhn.fhir.rest.server.method.SearchMethodBinding;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -57,7 +57,7 @@ public class SearchPreferHandlingInterceptor {
@Nonnull @Nonnull
private PreferHandlingEnum myDefaultBehaviour; private PreferHandlingEnum myDefaultBehaviour;
@Nullable @Nullable
private ISearchParamRetriever mySearchParamRetriever; private ISearchParamRegistry mySearchParamRegistry;
/** /**
* Constructor that uses the {@link RestfulServer} itself to determine * Constructor that uses the {@link RestfulServer} itself to determine
@ -68,12 +68,12 @@ public class SearchPreferHandlingInterceptor {
} }
/** /**
* Constructor that uses a dedicated {@link ISearchParamRetriever} instance. This is mainly * Constructor that uses a dedicated {@link ISearchParamRegistry} instance. This is mainly
* intended for the JPA server. * intended for the JPA server.
*/ */
public SearchPreferHandlingInterceptor(ISearchParamRetriever theSearchParamRetriever) { public SearchPreferHandlingInterceptor(ISearchParamRegistry theSearchParamRegistry) {
this(); this();
mySearchParamRetriever = theSearchParamRetriever; mySearchParamRegistry = theSearchParamRegistry;
} }
@Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLER_SELECTED) @Hook(Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLER_SELECTED)
@ -105,7 +105,7 @@ public class SearchPreferHandlingInterceptor {
private void removeUnwantedParams(PreferHandlingEnum theHandling, RequestDetails theRequestDetails) { private void removeUnwantedParams(PreferHandlingEnum theHandling, RequestDetails theRequestDetails) {
ISearchParamRetriever searchParamRetriever = mySearchParamRetriever; ISearchParamRegistry searchParamRetriever = mySearchParamRegistry;
if (searchParamRetriever == null) { if (searchParamRetriever == null) {
searchParamRetriever = ((RestfulServer) theRequestDetails.getServer()).createConfiguration(); searchParamRetriever = ((RestfulServer) theRequestDetails.getServer()).createConfiguration();
} }

View File

@ -26,7 +26,7 @@ import ca.uhn.fhir.rest.server.method.OperationParameter;
import ca.uhn.fhir.rest.server.method.SearchMethodBinding; import ca.uhn.fhir.rest.server.method.SearchMethodBinding;
import ca.uhn.fhir.rest.server.method.SearchParameter; import ca.uhn.fhir.rest.server.method.SearchParameter;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.rest.server.util.ISearchParamRetriever; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.FhirTerser; import ca.uhn.fhir.util.FhirTerser;
import com.google.common.collect.TreeMultimap; import com.google.common.collect.TreeMultimap;
import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBase;
@ -86,7 +86,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
private static final Logger ourLog = LoggerFactory.getLogger(ServerCapabilityStatementProvider.class); private static final Logger ourLog = LoggerFactory.getLogger(ServerCapabilityStatementProvider.class);
private final FhirContext myContext; private final FhirContext myContext;
private final RestfulServer myServer; private final RestfulServer myServer;
private final ISearchParamRetriever mySearchParamRetriever; private final ISearchParamRegistry mySearchParamRegistry;
private final RestfulServerConfiguration myServerConfiguration; private final RestfulServerConfiguration myServerConfiguration;
private final IValidationSupport myValidationSupport; private final IValidationSupport myValidationSupport;
private String myPublisher = "Not provided"; private String myPublisher = "Not provided";
@ -98,7 +98,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
public ServerCapabilityStatementProvider(RestfulServer theServer) { public ServerCapabilityStatementProvider(RestfulServer theServer) {
myServer = theServer; myServer = theServer;
myContext = theServer.getFhirContext(); myContext = theServer.getFhirContext();
mySearchParamRetriever = null; mySearchParamRegistry = null;
myServerConfiguration = null; myServerConfiguration = null;
myValidationSupport = null; myValidationSupport = null;
} }
@ -109,7 +109,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
public ServerCapabilityStatementProvider(FhirContext theContext, RestfulServerConfiguration theServerConfiguration) { public ServerCapabilityStatementProvider(FhirContext theContext, RestfulServerConfiguration theServerConfiguration) {
myContext = theContext; myContext = theContext;
myServerConfiguration = theServerConfiguration; myServerConfiguration = theServerConfiguration;
mySearchParamRetriever = null; mySearchParamRegistry = null;
myServer = null; myServer = null;
myValidationSupport = null; myValidationSupport = null;
} }
@ -117,9 +117,9 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
/** /**
* Constructor * Constructor
*/ */
public ServerCapabilityStatementProvider(RestfulServer theRestfulServer, ISearchParamRetriever theSearchParamRetriever, IValidationSupport theValidationSupport) { public ServerCapabilityStatementProvider(RestfulServer theRestfulServer, ISearchParamRegistry theSearchParamRegistry, IValidationSupport theValidationSupport) {
myContext = theRestfulServer.getFhirContext(); myContext = theRestfulServer.getFhirContext();
mySearchParamRetriever = theSearchParamRetriever; mySearchParamRegistry = theSearchParamRegistry;
myServer = theRestfulServer; myServer = theRestfulServer;
myServerConfiguration = null; myServerConfiguration = null;
myValidationSupport = theValidationSupport; myValidationSupport = theValidationSupport;
@ -349,16 +349,16 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
} }
ISearchParamRetriever searchParamRetriever; ISearchParamRegistry searchParamRegistry;
if (mySearchParamRetriever != null) { if (mySearchParamRegistry != null) {
searchParamRetriever = mySearchParamRetriever; searchParamRegistry = mySearchParamRegistry;
} else if (myServerConfiguration != null) { } else if (myServerConfiguration != null) {
searchParamRetriever = myServerConfiguration; searchParamRegistry = myServerConfiguration;
} else { } else {
searchParamRetriever = myServer.createConfiguration(); searchParamRegistry = myServer.createConfiguration();
} }
Map<String, RuntimeSearchParam> searchParams = searchParamRetriever.getActiveSearchParams(resourceName); Map<String, RuntimeSearchParam> searchParams = searchParamRegistry.getActiveSearchParams(resourceName);
for (RuntimeSearchParam next : searchParams.values()) { for (RuntimeSearchParam next : searchParams.values()) {
IBase searchParam = terser.addElement(resource, "searchParam"); IBase searchParam = terser.addElement(resource, "searchParam");
terser.addElement(searchParam, "name", next.getName()); terser.addElement(searchParam, "name", next.getName());
@ -412,7 +412,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
continue; continue;
} }
for (RuntimeSearchParam t : searchParamRetriever for (RuntimeSearchParam t : searchParamRegistry
.getActiveSearchParams(nextResourceName) .getActiveSearchParams(nextResourceName)
.values()) { .values()) {
if (t.getParamType() == RestSearchParameterTypeEnum.REFERENCE) { if (t.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {

View File

@ -0,0 +1,106 @@
package ca.uhn.fhir.rest.server.util;
/*
* #%L
* HAPI FHIR - Server Framework
* %%
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.context.phonetic.IPhoneticEncoder;
import ca.uhn.fhir.rest.api.Constants;
import org.hl7.fhir.instance.model.api.IAnyResource;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
// TODO: JA remove default methods
public interface ISearchParamRegistry {
/**
* @return Returns {@literal null} if no match
*/
RuntimeSearchParam getActiveSearchParam(String theResourceName, String theParamName);
/**
* @return Returns all active search params for the given resource
*/
Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName);
/**
* Request that the cache be refreshed now, in the current thread
*/
default void forceRefresh() {
}
;
/**
* Request that the cache be refreshed at the next convenient time (in a different thread)
*/
default void requestRefresh() {
}
/**
* When indexing a HumanName, if a StringEncoder is set in the context, then the "phonetic" search parameter will normalize
* the String using this encoder.
*
* @since 5.1.0
*/
default void setPhoneticEncoder(IPhoneticEncoder thePhoneticEncoder) {
}
default List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
return Collections.emptyList();
}
default List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
return Collections.emptyList();
}
/**
* Returns a collection containing all of the valid active search parameters. This method is intended for
* creating error messages for users as opposed to actual search processing. It will include meta parameters
* such as <code>_id</code> and <code>_lastUpdated</code>.
*/
default Collection<String> getValidSearchParameterNamesIncludingMeta(String theResourceName) {
TreeSet<String> retval;
Map<String, RuntimeSearchParam> searchParamMap = getActiveSearchParams(theResourceName);
if (searchParamMap == null) {
retval = new TreeSet<>();
} else {
retval = new TreeSet<>(searchParamMap.keySet());
}
retval.add(IAnyResource.SP_RES_ID);
retval.add(Constants.PARAM_LASTUPDATED);
return retval;
}
/**
* Fetch a SearchParameter by URL
*
* @return Returns <code>null</code> if it can't be found
*/
@Nullable
RuntimeSearchParam getActiveSearchParamByUrl(String theUrl);
}

Some files were not shown because too many files have changed in this diff Show More