mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-02-16 09:55:09 +00:00
Work in progress
This commit is contained in:
parent
ea5a023e17
commit
b4a362b8ee
@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.8
|
@ -82,87 +82,22 @@ public class FhirContext {
|
|||||||
private Map<String, Class<? extends IBaseResource>> myDefaultTypeForProfile = new HashMap<String, Class<? extends IBaseResource>>();
|
private Map<String, Class<? extends IBaseResource>> myDefaultTypeForProfile = new HashMap<String, Class<? extends IBaseResource>>();
|
||||||
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
private volatile Map<String, RuntimeResourceDefinition> myIdToResourceDefinition = Collections.emptyMap();
|
||||||
private boolean myInitialized;
|
private boolean myInitialized;
|
||||||
|
private boolean myInitializing;
|
||||||
private HapiLocalizer myLocalizer = new HapiLocalizer();
|
private HapiLocalizer myLocalizer = new HapiLocalizer();
|
||||||
private volatile Map<String, BaseRuntimeElementDefinition<?>> myNameToElementDefinition = Collections.emptyMap();
|
private volatile Map<String, BaseRuntimeElementDefinition<?>> myNameToElementDefinition = Collections.emptyMap();
|
||||||
private volatile Map<String, RuntimeResourceDefinition> myNameToResourceDefinition = Collections.emptyMap();
|
private volatile Map<String, RuntimeResourceDefinition> myNameToResourceDefinition = Collections.emptyMap();
|
||||||
private volatile Map<String, Class<? extends IBaseResource>> myNameToResourceType;
|
private volatile Map<String, Class<? extends IBaseResource>> myNameToResourceType;
|
||||||
private volatile INarrativeGenerator myNarrativeGenerator;
|
private volatile INarrativeGenerator myNarrativeGenerator;
|
||||||
private volatile IParserErrorHandler myParserErrorHandler = new LenientErrorHandler();
|
private volatile IParserErrorHandler myParserErrorHandler = new LenientErrorHandler();
|
||||||
|
private ParserOptions myParserOptions = new ParserOptions();
|
||||||
private Set<PerformanceOptionsEnum> myPerformanceOptions = new HashSet<PerformanceOptionsEnum>();
|
private Set<PerformanceOptionsEnum> myPerformanceOptions = new HashSet<PerformanceOptionsEnum>();
|
||||||
private Collection<Class<? extends IBaseResource>> myResourceTypesToScan;
|
private Collection<Class<? extends IBaseResource>> myResourceTypesToScan;
|
||||||
private volatile IRestfulClientFactory myRestfulClientFactory;
|
private volatile IRestfulClientFactory myRestfulClientFactory;
|
||||||
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||||
private final IFhirVersion myVersion;
|
|
||||||
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
|
||||||
private boolean myInitializing;
|
|
||||||
private IContextValidationSupport<?, ?, ?, ?, ?, ?> myValidationSupport;
|
private IContextValidationSupport<?, ?, ?, ?, ?, ?> myValidationSupport;
|
||||||
|
private final IFhirVersion myVersion;
|
||||||
|
|
||||||
/**
|
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
||||||
* Returns the validation support module configured for this context, creating a default
|
|
||||||
* implementation if no module has been passed in via the {@link #setValidationSupport(IContextValidationSupport)}
|
|
||||||
* method
|
|
||||||
* @see #setValidationSupport(IContextValidationSupport)
|
|
||||||
*/
|
|
||||||
public IContextValidationSupport<?, ?, ?, ?, ?, ?> getValidationSupport() {
|
|
||||||
if (myValidationSupport == null) {
|
|
||||||
myValidationSupport = myVersion.createValidationSupport();
|
|
||||||
}
|
|
||||||
return myValidationSupport;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new FluentPath engine which can be used to exvaluate
|
|
||||||
* path expressions over FHIR resources. Note that this engine will use the
|
|
||||||
* {@link IContextValidationSupport context validation support} module which is
|
|
||||||
* configured on the context at the time this method is called.
|
|
||||||
* <p>
|
|
||||||
* In other words, call {@link #setValidationSupport(IContextValidationSupport)} before
|
|
||||||
* calling {@link #newFluentPath()}
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Note that this feature was added for FHIR DSTU3 and is not available
|
|
||||||
* for contexts configured to use an older version of FHIR. Calling this method
|
|
||||||
* on a context for a previous version of fhir will result in an
|
|
||||||
* {@link UnsupportedOperationException}
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @since 2.2
|
|
||||||
*/
|
|
||||||
public IFluentPath newFluentPath() {
|
|
||||||
return myVersion.createFluentPathExecutor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the validation support module to use for this context. The validation support module
|
|
||||||
* is used to supply underlying infrastructure such as conformance resources (StructureDefinition, ValueSet, etc)
|
|
||||||
* as well as to provide terminology services to modules such as the validator and FluentPath executor
|
|
||||||
*/
|
|
||||||
public void setValidationSupport(IContextValidationSupport<?, ?, ?, ?, ?, ?> theValidationSupport) {
|
|
||||||
myValidationSupport = theValidationSupport;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParserOptions myParserOptions = new ParserOptions();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the parser options object which will be used to supply default
|
|
||||||
* options to newly created parsers
|
|
||||||
*
|
|
||||||
* @return The parser options - Will not return <code>null</code>
|
|
||||||
*/
|
|
||||||
public ParserOptions getParserOptions() {
|
|
||||||
return myParserOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the parser options object which will be used to supply default
|
|
||||||
* options to newly created parsers
|
|
||||||
*
|
|
||||||
* @param theParserOptions The parser options object - Must not be <code>null</code>
|
|
||||||
*/
|
|
||||||
public void setParserOptions(ParserOptions theParserOptions) {
|
|
||||||
Validate.notNull(theParserOptions, "theParserOptions must not be null");
|
|
||||||
myParserOptions = theParserOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated It is recommended that you use one of the static initializer methods instead
|
* @deprecated It is recommended that you use one of the static initializer methods instead
|
||||||
@ -172,7 +107,7 @@ public class FhirContext {
|
|||||||
public FhirContext() {
|
public FhirContext() {
|
||||||
this(EMPTY_LIST);
|
this(EMPTY_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated It is recommended that you use one of the static initializer methods instead
|
* @deprecated It is recommended that you use one of the static initializer methods instead
|
||||||
* of this method, e.g. {@link #forDstu2()} or {@link #forDstu3()}
|
* of this method, e.g. {@link #forDstu2()} or {@link #forDstu3()}
|
||||||
@ -282,7 +217,7 @@ public class FhirContext {
|
|||||||
validateInitialized();
|
validateInitialized();
|
||||||
return myNameToResourceDefinition.values();
|
return myNameToResourceDefinition.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default resource type for the given profile
|
* Returns the default resource type for the given profile
|
||||||
*
|
*
|
||||||
@ -332,7 +267,7 @@ public class FhirContext {
|
|||||||
validateInitialized();
|
validateInitialized();
|
||||||
return Collections.unmodifiableCollection(myClassToElementDefinition.values());
|
return Collections.unmodifiableCollection(myClassToElementDefinition.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
||||||
* caution
|
* caution
|
||||||
@ -348,6 +283,16 @@ public class FhirContext {
|
|||||||
return myNarrativeGenerator;
|
return myNarrativeGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parser options object which will be used to supply default
|
||||||
|
* options to newly created parsers
|
||||||
|
*
|
||||||
|
* @return The parser options - Will not return <code>null</code>
|
||||||
|
*/
|
||||||
|
public ParserOptions getParserOptions() {
|
||||||
|
return myParserOptions;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configured performance options
|
* Get the configured performance options
|
||||||
*/
|
*/
|
||||||
@ -449,6 +394,20 @@ public class FhirContext {
|
|||||||
return myIdToResourceDefinition.get(theId);
|
return myIdToResourceDefinition.get(theId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Return an unmodifiable collection containing all known resource definitions
|
||||||
|
// */
|
||||||
|
// public Collection<RuntimeResourceDefinition> getResourceDefinitions() {
|
||||||
|
//
|
||||||
|
// Set<Class<? extends IBase>> datatypes = Collections.emptySet();
|
||||||
|
// Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> existing = Collections.emptyMap();
|
||||||
|
// HashMap<String, Class<? extends IBaseResource>> types = new HashMap<String, Class<? extends IBaseResource>>();
|
||||||
|
// ModelScanner.scanVersionPropertyFile(datatypes, types, myVersion.getVersion(), existing);
|
||||||
|
// for (int next : types.)
|
||||||
|
//
|
||||||
|
// return Collections.unmodifiableCollection(myIdToResourceDefinition.values());
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the scanned runtime models. This is an advanced feature which is generally only needed for extending the
|
* Returns the scanned runtime models. This is an advanced feature which is generally only needed for extending the
|
||||||
* core library.
|
* core library.
|
||||||
@ -476,6 +435,19 @@ public class FhirContext {
|
|||||||
return myRuntimeChildUndeclaredExtensionDefinition;
|
return myRuntimeChildUndeclaredExtensionDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the validation support module configured for this context, creating a default
|
||||||
|
* implementation if no module has been passed in via the {@link #setValidationSupport(IContextValidationSupport)}
|
||||||
|
* method
|
||||||
|
* @see #setValidationSupport(IContextValidationSupport)
|
||||||
|
*/
|
||||||
|
public IContextValidationSupport<?, ?, ?, ?, ?, ?> getValidationSupport() {
|
||||||
|
if (myValidationSupport == null) {
|
||||||
|
myValidationSupport = myVersion.createValidationSupport();
|
||||||
|
}
|
||||||
|
return myValidationSupport;
|
||||||
|
}
|
||||||
|
|
||||||
public IFhirVersion getVersion() {
|
public IFhirVersion getVersion() {
|
||||||
return myVersion;
|
return myVersion;
|
||||||
}
|
}
|
||||||
@ -500,6 +472,28 @@ public class FhirContext {
|
|||||||
return myVersion.newBundleFactory(this);
|
return myVersion.newBundleFactory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new FluentPath engine which can be used to exvaluate
|
||||||
|
* path expressions over FHIR resources. Note that this engine will use the
|
||||||
|
* {@link IContextValidationSupport context validation support} module which is
|
||||||
|
* configured on the context at the time this method is called.
|
||||||
|
* <p>
|
||||||
|
* In other words, call {@link #setValidationSupport(IContextValidationSupport)} before
|
||||||
|
* calling {@link #newFluentPath()}
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Note that this feature was added for FHIR DSTU3 and is not available
|
||||||
|
* for contexts configured to use an older version of FHIR. Calling this method
|
||||||
|
* on a context for a previous version of fhir will result in an
|
||||||
|
* {@link UnsupportedOperationException}
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 2.2
|
||||||
|
*/
|
||||||
|
public IFluentPath newFluentPath() {
|
||||||
|
return myVersion.createFluentPathExecutor(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create and return a new JSON parser.
|
* Create and return a new JSON parser.
|
||||||
*
|
*
|
||||||
@ -783,6 +777,17 @@ public class FhirContext {
|
|||||||
myParserErrorHandler = theParserErrorHandler;
|
myParserErrorHandler = theParserErrorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the parser options object which will be used to supply default
|
||||||
|
* options to newly created parsers
|
||||||
|
*
|
||||||
|
* @param theParserOptions The parser options object - Must not be <code>null</code>
|
||||||
|
*/
|
||||||
|
public void setParserOptions(ParserOptions theParserOptions) {
|
||||||
|
Validate.notNull(theParserOptions, "theParserOptions must not be null");
|
||||||
|
myParserOptions = theParserOptions;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the configured performance options
|
* Sets the configured performance options
|
||||||
*
|
*
|
||||||
@ -818,6 +823,15 @@ public class FhirContext {
|
|||||||
this.myRestfulClientFactory = theRestfulClientFactory;
|
this.myRestfulClientFactory = theRestfulClientFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the validation support module to use for this context. The validation support module
|
||||||
|
* is used to supply underlying infrastructure such as conformance resources (StructureDefinition, ValueSet, etc)
|
||||||
|
* as well as to provide terminology services to modules such as the validator and FluentPath executor
|
||||||
|
*/
|
||||||
|
public void setValidationSupport(IContextValidationSupport<?, ?, ?, ?, ?, ?> theValidationSupport) {
|
||||||
|
myValidationSupport = theValidationSupport;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "cast" })
|
@SuppressWarnings({ "cast" })
|
||||||
private List<Class<? extends IElement>> toElementList(Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
private List<Class<? extends IElement>> toElementList(Collection<Class<? extends IBaseResource>> theResourceTypes) {
|
||||||
if (theResourceTypes == null) {
|
if (theResourceTypes == null) {
|
||||||
@ -850,6 +864,13 @@ public class FhirContext {
|
|||||||
return new FhirContext(FhirVersionEnum.DSTU2);
|
return new FhirContext(FhirVersionEnum.DSTU2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2 DSTU2} (2016 May DSTU3 Snapshot)
|
||||||
|
*/
|
||||||
|
public static FhirContext forDstu2_1() {
|
||||||
|
return new FhirContext(FhirVersionEnum.DSTU2_1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2_HL7ORG DSTU2} (using the Reference
|
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2_HL7ORG DSTU2} (using the Reference
|
||||||
* Implementation Structures)
|
* Implementation Structures)
|
||||||
@ -885,11 +906,4 @@ public class FhirContext {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new FhirContext with version {@link FhirVersionEnum#DSTU2 DSTU2} (2016 May DSTU3 Snapshot)
|
|
||||||
*/
|
|
||||||
public static FhirContext forDstu2_1() {
|
|
||||||
return new FhirContext(FhirVersionEnum.DSTU2_1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import java.util.Map.Entry;
|
|||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
import org.hl7.fhir.instance.model.api.*;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam.RuntimeSearchParamStatusEnum;
|
||||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||||
import ca.uhn.fhir.model.api.IDatatype;
|
import ca.uhn.fhir.model.api.IDatatype;
|
||||||
import ca.uhn.fhir.model.api.IElement;
|
import ca.uhn.fhir.model.api.IElement;
|
||||||
@ -437,7 +438,7 @@ class ModelScanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments, toTargetList(searchParam.target()));
|
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE);
|
||||||
theResourceDef.addSearchParam(param);
|
theResourceDef.addSearchParam(param);
|
||||||
nameToParam.put(param.getName(), param);
|
nameToParam.put(param.getName(), param);
|
||||||
}
|
}
|
||||||
@ -457,7 +458,7 @@ class ModelScanner {
|
|||||||
compositeOf.add(param);
|
compositeOf.add(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), RestSearchParameterTypeEnum.COMPOSITE, compositeOf, null, toTargetList(searchParam.target()));
|
RuntimeSearchParam param = new RuntimeSearchParam(searchParam.name(), searchParam.description(), searchParam.path(), RestSearchParameterTypeEnum.COMPOSITE, compositeOf, null, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE);
|
||||||
theResourceDef.addSearchParam(param);
|
theResourceDef.addSearchParam(param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,15 +37,17 @@ public class RuntimeSearchParam {
|
|||||||
private final String myPath;
|
private final String myPath;
|
||||||
private final Set<String> myTargets;
|
private final Set<String> myTargets;
|
||||||
private final Set<String> myProvidesMembershipInCompartments;
|
private final Set<String> myProvidesMembershipInCompartments;
|
||||||
|
private final RuntimeSearchParamStatusEnum myStatus;
|
||||||
|
|
||||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf,
|
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, List<RuntimeSearchParam> theCompositeOf,
|
||||||
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets) {
|
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
|
||||||
super();
|
super();
|
||||||
myName = theName;
|
myName = theName;
|
||||||
myDescription = theDescription;
|
myDescription = theDescription;
|
||||||
myPath = thePath;
|
myPath = thePath;
|
||||||
myParamType = theParamType;
|
myParamType = theParamType;
|
||||||
myCompositeOf = theCompositeOf;
|
myCompositeOf = theCompositeOf;
|
||||||
|
myStatus = theStatus;
|
||||||
if (theProvidesMembershipInCompartments != null && !theProvidesMembershipInCompartments.isEmpty()) {
|
if (theProvidesMembershipInCompartments != null && !theProvidesMembershipInCompartments.isEmpty()) {
|
||||||
myProvidesMembershipInCompartments = Collections.unmodifiableSet(theProvidesMembershipInCompartments);
|
myProvidesMembershipInCompartments = Collections.unmodifiableSet(theProvidesMembershipInCompartments);
|
||||||
} else {
|
} else {
|
||||||
@ -62,8 +64,12 @@ public class RuntimeSearchParam {
|
|||||||
return myTargets;
|
return myTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets) {
|
public RuntimeSearchParamStatusEnum getStatus() {
|
||||||
this(theName, theDescription, thePath, theParamType, null, theProvidesMembershipInCompartments, theTargets);
|
return myStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeSearchParam(String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus) {
|
||||||
|
this(theName, theDescription, thePath, theParamType, null, theProvidesMembershipInCompartments, theTargets, theStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RuntimeSearchParam> getCompositeOf() {
|
public List<RuntimeSearchParam> getCompositeOf() {
|
||||||
@ -108,4 +114,10 @@ public class RuntimeSearchParam {
|
|||||||
return myProvidesMembershipInCompartments;
|
return myProvidesMembershipInCompartments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum RuntimeSearchParamStatusEnum {
|
||||||
|
ACTIVE,
|
||||||
|
DRAFT,
|
||||||
|
RETIRED
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package ca.uhn.fhir.rest.annotation;
|
package ca.uhn.fhir.rest.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR - Core Library
|
* HAPI FHIR - Core Library
|
||||||
@ -10,7 +12,7 @@ package ca.uhn.fhir.rest.annotation;
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -22,19 +24,19 @@ package ca.uhn.fhir.rest.annotation;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
//import ca.uhn.fhir.testmodel.Patient; // TODO: qualify this correctly
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameter annotation which specifies a search parameter for a {@link Search} method.
|
* Parameter annotation which specifies a search parameter for a {@link Search} method.
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value=ElementType.PARAMETER)
|
||||||
public @interface OptionalParam {
|
public @interface OptionalParam {
|
||||||
|
|
||||||
public static final String ALLOW_CHAIN_ANY = "*";
|
public static final String ALLOW_CHAIN_ANY = "*";
|
||||||
@ -42,63 +44,63 @@ public @interface OptionalParam {
|
|||||||
public static final String ALLOW_CHAIN_NOTCHAINED = "";
|
public static final String ALLOW_CHAIN_NOTCHAINED = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For reference parameters ({@link ReferenceParam}) this value may be
|
* For reference parameters ({@link ReferenceParam}) this value may be
|
||||||
* used to indicate which chain values (if any) are <b>not</b> valid
|
* used to indicate which chain values (if any) are <b>not</b> valid
|
||||||
* for the given parameter. Values here will supercede any values specified
|
* for the given parameter. Values here will supercede any values specified
|
||||||
* in {@link #chainWhitelist()}
|
* in {@link #chainWhitelist()}
|
||||||
* <p>
|
* <p>
|
||||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||||
* this value must not be populated.
|
* this value must not be populated.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
String[] chainBlacklist() default {};
|
String[] chainBlacklist() default {};
|
||||||
|
|
||||||
/**
|
|
||||||
* For reference parameters ({@link ReferenceParam}) this value may be
|
|
||||||
* used to indicate which chain values (if any) are valid for the given
|
|
||||||
* parameter. If the list contains the value {@link #ALLOW_CHAIN_ANY}, all values are valid. (this is the default)
|
|
||||||
* If the list contains the value {@link #ALLOW_CHAIN_NOTCHAINED}
|
|
||||||
* then the reference param only supports the empty chain (i.e. the resource
|
|
||||||
* ID).
|
|
||||||
* <p>
|
|
||||||
* Valid values for this parameter include:
|
|
||||||
* </p>
|
|
||||||
* <ul>
|
|
||||||
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_NOTCHAINED }</code> - Only allow resource reference (no chaining allowed for this parameter)</li>
|
|
||||||
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_ANY }</code> - Allow any chaining at all (including a non chained value, <b>this is the default</b>)</li>
|
|
||||||
* <li><code>chainWhitelist={ "foo", "bar" }</code> - Allow property.foo and property.bar</li>
|
|
||||||
* </ul>
|
|
||||||
* <p>
|
|
||||||
* Any values specified in
|
|
||||||
* {@link #chainBlacklist()} will supercede (have priority over) values
|
|
||||||
* here.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
|
||||||
* this value must not be populated.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
String[] chainWhitelist() default {ALLOW_CHAIN_ANY};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For composite parameters ({@link CompositeParam}) this value may be
|
|
||||||
* used to indicate the parameter type(s) which may be referenced by this param.
|
|
||||||
* <p>
|
|
||||||
* If the parameter annotated with this annotation is not a {@link CompositeParam},
|
|
||||||
* this value must not be populated.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the name for the parameter. Generally this should be a
|
* For reference parameters ({@link ReferenceParam}) this value may be
|
||||||
|
* used to indicate which chain values (if any) are valid for the given
|
||||||
|
* parameter. If the list contains the value {@link #ALLOW_CHAIN_ANY}, all values are valid. (this is the default)
|
||||||
|
* If the list contains the value {@link #ALLOW_CHAIN_NOTCHAINED}
|
||||||
|
* then the reference param only supports the empty chain (i.e. the resource
|
||||||
|
* ID).
|
||||||
|
* <p>
|
||||||
|
* Valid values for this parameter include:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_NOTCHAINED }</code> - Only allow resource reference (no chaining allowed for this parameter)</li>
|
||||||
|
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_ANY }</code> - Allow any chaining at all (including a non chained value, <b>this is the default</b>)</li>
|
||||||
|
* <li><code>chainWhitelist={ "foo", "bar" }</code> - Allow property.foo and property.bar</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Any values specified in
|
||||||
|
* {@link #chainBlacklist()} will supercede (have priority over) values
|
||||||
|
* here.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||||
|
* this value must not be populated.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
String[] chainWhitelist() default { ALLOW_CHAIN_ANY };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For composite parameters ({@link CompositeParam}) this value may be
|
||||||
|
* used to indicate the parameter type(s) which may be referenced by this param.
|
||||||
|
* <p>
|
||||||
|
* If the parameter annotated with this annotation is not a {@link CompositeParam},
|
||||||
|
* this value must not be populated.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
Class<? extends IQueryParameterType>[] compositeTypes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the name for the parameter. Generally this should be a
|
||||||
* simple string (e.g. "name", or "identifier") which will be the name
|
* simple string (e.g. "name", or "identifier") which will be the name
|
||||||
* of the URL parameter used to populate this method parameter.
|
* of the URL parameter used to populate this method parameter.
|
||||||
* <p>
|
* <p>
|
||||||
* Most resource model classes have constants which may be used to
|
* Most resource model classes have constants which may be used to
|
||||||
* supply values for this field, e.g. <code>Patient.SP_NAME</code> or
|
* supply values for this field, e.g. <code>Patient.SP_NAME</code> or
|
||||||
* <code>Observation.SP_DATE</code>
|
* <code>Observation.SP_DATE</code>
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If you wish to specify a parameter for a resource reference which
|
* If you wish to specify a parameter for a resource reference which
|
||||||
* only accepts a specific chained value, it is also valid to supply
|
* only accepts a specific chained value, it is also valid to supply
|
||||||
@ -109,13 +111,13 @@ public @interface OptionalParam {
|
|||||||
*/
|
*/
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For resource reference parameters ({@link ReferenceParam}) this value may be
|
* For resource reference parameters ({@link ReferenceParam}) this value may be
|
||||||
* used to indicate the resource type(s) which may be referenced by this param.
|
* used to indicate the resource type(s) which may be referenced by this param.
|
||||||
* <p>
|
* <p>
|
||||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||||
* this value must not be populated.
|
* this value must not be populated.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
Class<? extends IBaseResource>[] targetTypes() default {};
|
Class<? extends IBaseResource>[] targetTypes() default {};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package ca.uhn.fhir.rest.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On a {@link Search} method, a parameter marked with this annotation
|
||||||
|
* will receive search parameters not captured by other parameters.
|
||||||
|
* <p>
|
||||||
|
* Parameters with this annotation must be of type
|
||||||
|
* {@code Map<String, List<String>>}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value=ElementType.PARAMETER)
|
||||||
|
public @interface RawParam {
|
||||||
|
// nothing
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package ca.uhn.fhir.rest.annotation;
|
package ca.uhn.fhir.rest.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR - Core Library
|
* HAPI FHIR - Core Library
|
||||||
@ -10,7 +12,7 @@ package ca.uhn.fhir.rest.annotation;
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -22,18 +24,19 @@ package ca.uhn.fhir.rest.annotation;
|
|||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.rest.param.CompositeParam;
|
import ca.uhn.fhir.rest.param.CompositeParam;
|
||||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||||
//import ca.uhn.fhir.testmodel.Patient; // TODO: qualify this correctly
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
/**
|
/**
|
||||||
* Parameter annotation which specifies a search parameter for a {@link Search} method.
|
* Parameter annotation which specifies a search parameter for a {@link Search} method.
|
||||||
*/
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(value=ElementType.PARAMETER)
|
||||||
public @interface RequiredParam {
|
public @interface RequiredParam {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,32 +48,32 @@ public @interface RequiredParam {
|
|||||||
*/
|
*/
|
||||||
String[] chainBlacklist() default {};
|
String[] chainBlacklist() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For reference parameters ({@link ReferenceParam}) this value may be
|
* For reference parameters ({@link ReferenceParam}) this value may be
|
||||||
* used to indicate which chain values (if any) are valid for the given
|
* used to indicate which chain values (if any) are valid for the given
|
||||||
* parameter. If the list contains the value {@link OptionalParam#ALLOW_CHAIN_ANY}, all values are valid. (this is the default)
|
* parameter. If the list contains the value {@link OptionalParam#ALLOW_CHAIN_ANY}, all values are valid. (this is the default)
|
||||||
* If the list contains the value {@link OptionalParam#ALLOW_CHAIN_NOTCHAINED}
|
* If the list contains the value {@link OptionalParam#ALLOW_CHAIN_NOTCHAINED}
|
||||||
* then the reference param only supports the empty chain (i.e. the resource
|
* then the reference param only supports the empty chain (i.e. the resource
|
||||||
* ID).
|
* ID).
|
||||||
* <p>
|
* <p>
|
||||||
* Valid values for this parameter include:
|
* Valid values for this parameter include:
|
||||||
* </p>
|
* </p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_NOTCHAINED }</code> - Only allow resource reference (no chaining allowed for this parameter)</li>
|
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_NOTCHAINED }</code> - Only allow resource reference (no chaining allowed for this parameter)</li>
|
||||||
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_ANY }</code> - Allow any chaining at all (including a non chained value, <b>this is the default</b>)</li>
|
* <li><code>chainWhitelist={ OptionalParam.ALLOW_CHAIN_ANY }</code> - Allow any chaining at all (including a non chained value, <b>this is the default</b>)</li>
|
||||||
* <li><code>chainWhitelist={ "foo", "bar" }</code> - Allow property.foo and property.bar</li>
|
* <li><code>chainWhitelist={ "foo", "bar" }</code> - Allow property.foo and property.bar</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* Any values specified in
|
* Any values specified in
|
||||||
* {@link #chainBlacklist()} will supercede (have priority over) values
|
* {@link #chainBlacklist()} will supercede (have priority over) values
|
||||||
* here.
|
* here.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
* If the parameter annotated with this annotation is not a {@link ReferenceParam},
|
||||||
* this value must not be populated.
|
* this value must not be populated.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
String[] chainWhitelist() default {OptionalParam.ALLOW_CHAIN_ANY};
|
String[] chainWhitelist() default { OptionalParam.ALLOW_CHAIN_ANY };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For composite parameters ({@link CompositeParam}) this parameter may be used to indicate the parameter type(s) which may be referenced by this param.
|
* For composite parameters ({@link CompositeParam}) this parameter may be used to indicate the parameter type(s) which may be referenced by this param.
|
||||||
|
@ -407,6 +407,8 @@ public class MethodUtil {
|
|||||||
parameter.setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
parameter.setType(theContext, parameterType, innerCollectionType, outerCollectionType);
|
||||||
MethodUtil.extractDescription(parameter, annotations);
|
MethodUtil.extractDescription(parameter, annotations);
|
||||||
param = parameter;
|
param = parameter;
|
||||||
|
} else if (nextAnnotation instanceof RawParam) {
|
||||||
|
param = new RawParamsParmeter(parameters);
|
||||||
} else if (nextAnnotation instanceof IncludeParam) {
|
} else if (nextAnnotation instanceof IncludeParam) {
|
||||||
Class<? extends Collection<Include>> instantiableCollectionType;
|
Class<? extends Collection<Include>> instantiableCollectionType;
|
||||||
Class<?> specType;
|
Class<?> specType;
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
package ca.uhn.fhir.rest.method;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.annotation.RawParam;
|
||||||
|
import ca.uhn.fhir.rest.method.SearchMethodBinding.QualifierDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
|
public class RawParamsParmeter implements IParameter {
|
||||||
|
|
||||||
|
private final List<IParameter> myAllMethodParameters;
|
||||||
|
|
||||||
|
public RawParamsParmeter(List<IParameter> theParameters) {
|
||||||
|
myAllMethodParameters = theParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource)
|
||||||
|
throws InternalErrorException {
|
||||||
|
// not supported on client for now
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
|
||||||
|
HashMap<String, List<String>> retVal = null;
|
||||||
|
|
||||||
|
for (String nextName : theRequest.getParameters().keySet()) {
|
||||||
|
if (nextName.startsWith("_")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QualifierDetails qualifiers = SearchMethodBinding.extractQualifiersFromParameterName(nextName);
|
||||||
|
|
||||||
|
boolean alreadyCaptured = false;
|
||||||
|
for (IParameter nextParameter : myAllMethodParameters) {
|
||||||
|
if (nextParameter instanceof SearchParameter) {
|
||||||
|
SearchParameter nextSearchParam = (SearchParameter)nextParameter;
|
||||||
|
if (nextSearchParam.getName().equals(qualifiers.getParamName())) {
|
||||||
|
if (qualifiers.passes(nextSearchParam.getQualifierWhitelist(), nextSearchParam.getQualifierBlacklist())) {
|
||||||
|
alreadyCaptured = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alreadyCaptured) {
|
||||||
|
if (retVal == null) {
|
||||||
|
retVal = new HashMap<String, List<String>>();
|
||||||
|
}
|
||||||
|
retVal.put(nextName, Arrays.asList(theRequest.getParameters().get(nextName)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||||
|
Validate.isTrue(theParameterType.equals(Map.class), "Parameter with @" + RawParam.class + " must be of type Map<String, List<String>>");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -130,11 +130,7 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ReturnTypeEnum getReturnType() {
|
public ReturnTypeEnum getReturnType() {
|
||||||
// if (getContext().getVersion().getVersion() == FhirVersionEnum.DSTU1) {
|
|
||||||
return ReturnTypeEnum.BUNDLE;
|
return ReturnTypeEnum.BUNDLE;
|
||||||
// } else {
|
|
||||||
// return ReturnTypeEnum.RESOURCE;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -406,14 +402,20 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||||||
if (dotIdx < colonIdx) {
|
if (dotIdx < colonIdx) {
|
||||||
retVal.setDotQualifier(theParamName.substring(dotIdx, colonIdx));
|
retVal.setDotQualifier(theParamName.substring(dotIdx, colonIdx));
|
||||||
retVal.setColonQualifier(theParamName.substring(colonIdx));
|
retVal.setColonQualifier(theParamName.substring(colonIdx));
|
||||||
|
retVal.setParamName(theParamName.substring(0, dotIdx));
|
||||||
} else {
|
} else {
|
||||||
retVal.setColonQualifier(theParamName.substring(colonIdx, dotIdx));
|
retVal.setColonQualifier(theParamName.substring(colonIdx, dotIdx));
|
||||||
retVal.setDotQualifier(theParamName.substring(dotIdx));
|
retVal.setDotQualifier(theParamName.substring(dotIdx));
|
||||||
|
retVal.setParamName(theParamName.substring(0, colonIdx));
|
||||||
}
|
}
|
||||||
} else if (dotIdx != -1) {
|
} else if (dotIdx != -1) {
|
||||||
retVal.setDotQualifier(theParamName.substring(dotIdx));
|
retVal.setDotQualifier(theParamName.substring(dotIdx));
|
||||||
|
retVal.setParamName(theParamName.substring(0, dotIdx));
|
||||||
} else if (colonIdx != -1) {
|
} else if (colonIdx != -1) {
|
||||||
retVal.setColonQualifier(theParamName.substring(colonIdx));
|
retVal.setColonQualifier(theParamName.substring(colonIdx));
|
||||||
|
retVal.setParamName(theParamName.substring(0, colonIdx));
|
||||||
|
} else {
|
||||||
|
retVal.setParamName(theParamName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
@ -423,6 +425,7 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||||||
|
|
||||||
private String myColonQualifier;
|
private String myColonQualifier;
|
||||||
private String myDotQualifier;
|
private String myDotQualifier;
|
||||||
|
private String myParamName;
|
||||||
|
|
||||||
public boolean passes(Set<String> theQualifierWhitelist, Set<String> theQualifierBlacklist) {
|
public boolean passes(Set<String> theQualifierWhitelist, Set<String> theQualifierBlacklist) {
|
||||||
if (theQualifierWhitelist != null) {
|
if (theQualifierWhitelist != null) {
|
||||||
@ -468,6 +471,14 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setParamName(String theParamName) {
|
||||||
|
myParamName = theParamName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParamName() {
|
||||||
|
return myParamName;
|
||||||
|
}
|
||||||
|
|
||||||
public void setColonQualifier(String theColonQualifier) {
|
public void setColonQualifier(String theColonQualifier) {
|
||||||
myColonQualifier = theColonQualifier;
|
myColonQualifier = theColonQualifier;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
5
hapi-fhir-jacoco/.settings/org.eclipse.jdt.core.prefs
Normal file
5
hapi-fhir-jacoco/.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.jpa.config;
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -29,7 +29,9 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParamExtractorDstu1;
|
import ca.uhn.fhir.jpa.dao.SearchParamExtractorDstu1;
|
||||||
|
import ca.uhn.fhir.jpa.dao.SearchParamRegistryDstu1;
|
||||||
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu1;
|
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu1;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
@ -39,9 +41,10 @@ import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
|||||||
public class BaseDstu1Config extends BaseConfig {
|
public class BaseDstu1Config extends BaseConfig {
|
||||||
private static FhirContext ourFhirContextDstu1;
|
private static FhirContext ourFhirContextDstu1;
|
||||||
|
|
||||||
@Bean(autowire = Autowire.BY_TYPE)
|
@Bean
|
||||||
public IHapiTerminologySvc terminologyService() {
|
@Primary
|
||||||
return new HapiTerminologySvcDstu1();
|
public FhirContext defaultFhirContext() {
|
||||||
|
return fhirContextDstu1();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(name = "myFhirContextDstu1")
|
@Bean(name = "myFhirContextDstu1")
|
||||||
@ -53,19 +56,22 @@ public class BaseDstu1Config extends BaseConfig {
|
|||||||
return ourFhirContextDstu1;
|
return ourFhirContextDstu1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Primary
|
|
||||||
public FhirContext defaultFhirContext() {
|
|
||||||
return fhirContextDstu1();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(name = "mySystemDaoDstu1", autowire = Autowire.BY_NAME)
|
@Bean(name = "mySystemDaoDstu1", autowire = Autowire.BY_NAME)
|
||||||
public ca.uhn.fhir.jpa.dao.IFhirSystemDao<List<IResource>, MetaDt> fhirSystemDaoDstu1() {
|
public ca.uhn.fhir.jpa.dao.IFhirSystemDao<List<IResource>, MetaDt> fhirSystemDaoDstu1() {
|
||||||
ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu1 retVal = new ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu1();
|
ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu1 retVal = new ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu1();
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
|
public SearchParamExtractorDstu1 searchParamExtractor() {
|
||||||
|
return new SearchParamExtractorDstu1();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ISearchParamRegistry searchParamRegistry() {
|
||||||
|
return new SearchParamRegistryDstu1();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(name = "mySystemProviderDstu1")
|
@Bean(name = "mySystemProviderDstu1")
|
||||||
public ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1 systemDaoDstu1() {
|
public ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1 systemDaoDstu1() {
|
||||||
ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1 retVal = new ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1();
|
ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1 retVal = new ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu1();
|
||||||
@ -73,9 +79,9 @@ public class BaseDstu1Config extends BaseConfig {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(autowire=Autowire.BY_TYPE)
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
public SearchParamExtractorDstu1 searchParamExtractor() {
|
public IHapiTerminologySvc terminologyService() {
|
||||||
return new SearchParamExtractorDstu1();
|
return new HapiTerminologySvcDstu1();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,9 @@ import ca.uhn.fhir.context.FhirContext;
|
|||||||
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
|
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||||
|
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParamExtractorDstu2;
|
import ca.uhn.fhir.jpa.dao.SearchParamExtractorDstu2;
|
||||||
|
import ca.uhn.fhir.jpa.dao.SearchParamRegistryDstu2;
|
||||||
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu2;
|
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu2;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
@ -84,6 +86,11 @@ public class BaseDstu2Config extends BaseConfig {
|
|||||||
return new SearchParamExtractorDstu2();
|
return new SearchParamExtractorDstu2();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ISearchParamRegistry searchParamRegistry() {
|
||||||
|
return new SearchParamRegistryDstu2();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(name = "mySystemDaoDstu2", autowire = Autowire.BY_NAME)
|
@Bean(name = "mySystemDaoDstu2", autowire = Autowire.BY_NAME)
|
||||||
public IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDaoDstu2() {
|
public IFhirSystemDao<ca.uhn.fhir.model.dstu2.resource.Bundle, MetaDt> systemDaoDstu2() {
|
||||||
ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2 retVal = new ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2();
|
ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2 retVal = new ca.uhn.fhir.jpa.dao.FhirSystemDaoDstu2();
|
||||||
|
@ -14,7 +14,7 @@ import org.hl7.fhir.dstu3.validation.IResourceValidator.BestPracticeWarningLevel
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -37,7 +37,9 @@ import ca.uhn.fhir.jpa.config.BaseConfig;
|
|||||||
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
|
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||||
|
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.jpa.dao.dstu3.SearchParamExtractorDstu3;
|
import ca.uhn.fhir.jpa.dao.dstu3.SearchParamExtractorDstu3;
|
||||||
|
import ca.uhn.fhir.jpa.dao.dstu3.SearchParamRegistryDstu3;
|
||||||
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
|
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
|
||||||
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu3;
|
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu3;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
||||||
@ -50,25 +52,15 @@ import ca.uhn.fhir.validation.IValidatorModule;
|
|||||||
@EnableTransactionManagement
|
@EnableTransactionManagement
|
||||||
public class BaseDstu3Config extends BaseConfig {
|
public class BaseDstu3Config extends BaseConfig {
|
||||||
|
|
||||||
@Bean(autowire = Autowire.BY_TYPE)
|
|
||||||
public IHapiTerminologySvcDstu3 terminologyService() {
|
|
||||||
return new HapiTerminologySvcDstu3();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(autowire = Autowire.BY_TYPE)
|
|
||||||
public IHapiTerminologyLoaderSvc terminologyLoaderService() {
|
|
||||||
return new TerminologyLoaderSvc();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Primary
|
@Primary
|
||||||
public FhirContext fhirContextDstu3() {
|
public FhirContext fhirContextDstu3() {
|
||||||
FhirContext retVal = FhirContext.forDstu3();
|
FhirContext retVal = FhirContext.forDstu3();
|
||||||
|
|
||||||
// Don't strip versions in some places
|
// Don't strip versions in some places
|
||||||
ParserOptions parserOptions = retVal.getParserOptions();
|
ParserOptions parserOptions = retVal.getParserOptions();
|
||||||
parserOptions.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference");
|
parserOptions.setDontStripVersionsFromReferencesAtPaths("AuditEvent.entity.reference");
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +85,16 @@ public class BaseDstu3Config extends BaseConfig {
|
|||||||
return searchDao;
|
return searchDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
|
public SearchParamExtractorDstu3 searchParamExtractor() {
|
||||||
|
return new SearchParamExtractorDstu3();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ISearchParamRegistry searchParamRegistry() {
|
||||||
|
return new SearchParamRegistryDstu3();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(name = "mySystemDaoDstu3", autowire = Autowire.BY_NAME)
|
@Bean(name = "mySystemDaoDstu3", autowire = Autowire.BY_NAME)
|
||||||
public IFhirSystemDao<org.hl7.fhir.dstu3.model.Bundle, org.hl7.fhir.dstu3.model.Meta> systemDaoDstu3() {
|
public IFhirSystemDao<org.hl7.fhir.dstu3.model.Bundle, org.hl7.fhir.dstu3.model.Meta> systemDaoDstu3() {
|
||||||
ca.uhn.fhir.jpa.dao.dstu3.FhirSystemDaoDstu3 retVal = new ca.uhn.fhir.jpa.dao.dstu3.FhirSystemDaoDstu3();
|
ca.uhn.fhir.jpa.dao.dstu3.FhirSystemDaoDstu3 retVal = new ca.uhn.fhir.jpa.dao.dstu3.FhirSystemDaoDstu3();
|
||||||
@ -107,23 +109,27 @@ public class BaseDstu3Config extends BaseConfig {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
|
public IHapiTerminologyLoaderSvc terminologyLoaderService() {
|
||||||
|
return new TerminologyLoaderSvc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
|
public IHapiTerminologySvcDstu3 terminologyService() {
|
||||||
|
return new HapiTerminologySvcDstu3();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
|
public TerminologyUploaderProviderDstu3 terminologyUploaderProvider() {
|
||||||
|
TerminologyUploaderProviderDstu3 retVal = new TerminologyUploaderProviderDstu3();
|
||||||
|
retVal.setContext(fhirContextDstu3());
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Primary
|
@Primary
|
||||||
@Bean(autowire = Autowire.BY_NAME, name = "myJpaValidationSupportChainDstu3")
|
@Bean(autowire = Autowire.BY_NAME, name = "myJpaValidationSupportChainDstu3")
|
||||||
public IValidationSupport validationSupportChainDstu3() {
|
public IValidationSupport validationSupportChainDstu3() {
|
||||||
return new JpaValidationSupportChainDstu3();
|
return new JpaValidationSupportChainDstu3();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(autowire = Autowire.BY_TYPE)
|
|
||||||
public SearchParamExtractorDstu3 searchParamExtractor() {
|
|
||||||
return new SearchParamExtractorDstu3();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(autowire=Autowire.BY_TYPE)
|
|
||||||
public TerminologyUploaderProviderDstu3 terminologyUploaderProvider() {
|
|
||||||
TerminologyUploaderProviderDstu3 retVal = new TerminologyUploaderProviderDstu3();
|
|
||||||
retVal.setContext(fhirContextDstu3());
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -863,6 +863,9 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
return search(map);
|
return search(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISearchParamRegistry mySerarchParamRegistry;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBundleProvider search(final SearchParameterMap theParams) {
|
public IBundleProvider search(final SearchParameterMap theParams) {
|
||||||
// Notify interceptors
|
// Notify interceptors
|
||||||
@ -870,7 +873,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
|
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
|
||||||
|
|
||||||
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao,
|
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao,
|
||||||
myTerminologySvc);
|
myTerminologySvc, mySerarchParamRegistry);
|
||||||
builder.setType(getResourceType(), getResourceName());
|
builder.setType(getResourceType(), getResourceName());
|
||||||
return builder.search(theParams);
|
return builder.search(theParams);
|
||||||
}
|
}
|
||||||
@ -899,7 +902,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
theParams.setPersistResults(false);
|
theParams.setPersistResults(false);
|
||||||
|
|
||||||
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao,
|
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao,
|
||||||
myTerminologySvc);
|
myTerminologySvc, mySerarchParamRegistry);
|
||||||
builder.setType(getResourceType(), getResourceName());
|
builder.setType(getResourceType(), getResourceName());
|
||||||
builder.search(theParams);
|
builder.search(theParams);
|
||||||
return builder.doGetPids();
|
return builder.doGetPids();
|
||||||
|
@ -21,9 +21,12 @@ package ca.uhn.fhir.jpa.dao;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
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;
|
||||||
|
|
||||||
@ -42,12 +45,32 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISearchParamRegistry mySearchParamRegistry;
|
||||||
|
|
||||||
public BaseSearchParamExtractor() {
|
public BaseSearchParamExtractor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseSearchParamExtractor(FhirContext theCtx) {
|
public BaseSearchParamExtractor(FhirContext theCtx, ISearchParamRegistry theSearchParamRegistry) {
|
||||||
myContext = theCtx;
|
myContext = theCtx;
|
||||||
|
mySearchParamRegistry = theSearchParamRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PathAndRef> extractResourceLinks(IBaseResource theResource, RuntimeSearchParam theNextSpDef) {
|
||||||
|
List<PathAndRef> refs = new ArrayList<PathAndRef>();
|
||||||
|
String[] nextPathsSplit = theNextSpDef.getPath().split("\\|");
|
||||||
|
for (String nextPath : nextPathsSplit) {
|
||||||
|
nextPath = nextPath.trim();
|
||||||
|
for (Object nextObject : extractValues(nextPath, theResource)) {
|
||||||
|
if (nextObject == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
refs.add(new PathAndRef(nextPath, nextObject));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Object> extractValues(String thePaths, IBaseResource theResource) {
|
protected List<Object> extractValues(String thePaths, IBaseResource theResource) {
|
||||||
@ -70,26 +93,18 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||||||
return myContext;
|
return myContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Collection<RuntimeSearchParam> getSearchParams(IBaseResource theResource) {
|
||||||
|
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||||
|
Collection<RuntimeSearchParam> retVal = mySearchParamRegistry.getActiveSearchParams(def.getName()).values();
|
||||||
|
List<RuntimeSearchParam> defaultList= Collections.emptyList();
|
||||||
|
retVal = ObjectUtils.defaultIfNull(retVal, defaultList);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void setContextForUnitTest(FhirContext theContext) {
|
void setContextForUnitTest(FhirContext theContext) {
|
||||||
myContext = theContext;
|
myContext = theContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<PathAndRef> extractResourceLinks(IBaseResource theResource, RuntimeSearchParam theNextSpDef) {
|
|
||||||
List<PathAndRef> refs = new ArrayList<PathAndRef>();
|
|
||||||
String[] nextPathsSplit = theNextSpDef.getPath().split("\\|");
|
|
||||||
for (String nextPath : nextPathsSplit) {
|
|
||||||
nextPath = nextPath.trim();
|
|
||||||
for (Object nextObject : extractValues(nextPath, theResource)) {
|
|
||||||
if (nextObject == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
refs.add(new PathAndRef(nextPath, nextObject));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return refs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
|
|
||||||
|
public abstract class BaseSearchParamRegistry implements ISearchParamRegistry {
|
||||||
|
|
||||||
|
private Map<String, Map<String, RuntimeSearchParam>> myBuiltInSearchParams;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FhirContext myCtx;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Collection<IFhirResourceDao<?>> myDaos;
|
||||||
|
|
||||||
|
public BaseSearchParamRegistry() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void forceRefresh() {
|
||||||
|
// nothing by default
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Map<String, RuntimeSearchParam>> getBuiltInSearchParams() {
|
||||||
|
return myBuiltInSearchParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
||||||
|
Validate.notBlank(theResourceName, "theResourceName must not be blank or null");
|
||||||
|
|
||||||
|
return myBuiltInSearchParams.get(theResourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void postConstruct() {
|
||||||
|
Map<String, Map<String, RuntimeSearchParam>> resourceNameToSearchParams = new HashMap<String, Map<String,RuntimeSearchParam>>();
|
||||||
|
|
||||||
|
for (IFhirResourceDao<?> nextDao : myDaos) {
|
||||||
|
RuntimeResourceDefinition nextResDef = myCtx.getResourceDefinition(nextDao.getResourceType());
|
||||||
|
String nextResourceName = nextResDef.getName();
|
||||||
|
HashMap<String, RuntimeSearchParam> nameToParam = new HashMap<String, RuntimeSearchParam>();
|
||||||
|
resourceNameToSearchParams.put(nextResourceName, nameToParam);
|
||||||
|
|
||||||
|
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
|
||||||
|
nameToParam.put(nextSp.getName(), nextSp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myBuiltInSearchParams = Collections.unmodifiableMap(resourceNameToSearchParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,7 +16,7 @@ import org.apache.commons.lang3.time.DateUtils;
|
|||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
@ -35,26 +35,28 @@ public class DaoConfig {
|
|||||||
// ***
|
// ***
|
||||||
// update setter javadoc if default changes
|
// update setter javadoc if default changes
|
||||||
// ***
|
// ***
|
||||||
private boolean myAllowExternalReferences = false;
|
private boolean myAllowExternalReferences = false;
|
||||||
|
|
||||||
// ***
|
// ***
|
||||||
// update setter javadoc if default changes
|
// update setter javadoc if default changes
|
||||||
// ***
|
// ***
|
||||||
private boolean myAllowInlineMatchUrlReferences = false;
|
private boolean myAllowInlineMatchUrlReferences = false;
|
||||||
|
|
||||||
private boolean myAllowMultipleDelete;
|
private boolean myAllowMultipleDelete;
|
||||||
|
private boolean myDefaultSearchParamsCanBeOverridden = false;
|
||||||
// ***
|
// ***
|
||||||
// update setter javadoc if default changes
|
// update setter javadoc if default changes
|
||||||
// ***
|
// ***
|
||||||
private int myDeferIndexingForCodesystemsOfSize = 2000;
|
private int myDeferIndexingForCodesystemsOfSize = 2000;
|
||||||
private boolean myDeleteStaleSearches = true;
|
private boolean myDeleteStaleSearches = true;
|
||||||
|
|
||||||
// ***
|
// ***
|
||||||
// update setter javadoc if default changes
|
// update setter javadoc if default changes
|
||||||
// ***
|
// ***
|
||||||
private long myExpireSearchResultsAfterMillis = DateUtils.MILLIS_PER_HOUR;
|
private long myExpireSearchResultsAfterMillis = DateUtils.MILLIS_PER_HOUR;
|
||||||
|
|
||||||
private int myHardTagListLimit = 1000;
|
private int myHardTagListLimit = 1000;
|
||||||
|
|
||||||
private int myIncludeLimit = 2000;
|
private int myIncludeLimit = 2000;
|
||||||
|
|
||||||
// ***
|
// ***
|
||||||
@ -63,19 +65,19 @@ public class DaoConfig {
|
|||||||
private boolean myIndexContainedResources = true;
|
private boolean myIndexContainedResources = true;
|
||||||
|
|
||||||
private List<IServerInterceptor> myInterceptors;
|
private List<IServerInterceptor> myInterceptors;
|
||||||
|
|
||||||
// ***
|
// ***
|
||||||
// update setter javadoc if default changes
|
// update setter javadoc if default changes
|
||||||
// ***
|
// ***
|
||||||
private int myMaximumExpansionSize = 5000;
|
private int myMaximumExpansionSize = 5000;
|
||||||
|
|
||||||
private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
|
private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
|
||||||
|
|
||||||
private boolean mySchedulingDisabled;
|
private boolean mySchedulingDisabled;
|
||||||
|
|
||||||
private boolean mySubscriptionEnabled;
|
private boolean mySubscriptionEnabled;
|
||||||
|
|
||||||
private long mySubscriptionPollDelay = 1000;
|
private long mySubscriptionPollDelay = 1000;
|
||||||
|
|
||||||
private Long mySubscriptionPurgeInactiveAfterMillis;
|
private Long mySubscriptionPurgeInactiveAfterMillis;
|
||||||
|
|
||||||
private Set<String> myTreatBaseUrlsAsLocal = new HashSet<String>();
|
private Set<String> myTreatBaseUrlsAsLocal = new HashSet<String>();
|
||||||
@ -91,42 +93,44 @@ public class DaoConfig {
|
|||||||
public int getDeferIndexingForCodesystemsOfSize() {
|
public int getDeferIndexingForCodesystemsOfSize() {
|
||||||
return myDeferIndexingForCodesystemsOfSize;
|
return myDeferIndexingForCodesystemsOfSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the number of milliseconds that search results for a given client search
|
* Sets the number of milliseconds that search results for a given client search
|
||||||
* should be preserved before being purged from the database.
|
* should be preserved before being purged from the database.
|
||||||
* <p>
|
* <p>
|
||||||
* Search results are stored in the database so that they can be paged over multiple
|
* Search results are stored in the database so that they can be paged over multiple
|
||||||
* requests. After this
|
* requests. After this
|
||||||
* number of milliseconds, they will be deleted from the database, and any paging links
|
* number of milliseconds, they will be deleted from the database, and any paging links
|
||||||
* (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
|
* (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @see To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
|
* @see To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public long getExpireSearchResultsAfterMillis() {
|
public long getExpireSearchResultsAfterMillis() {
|
||||||
return myExpireSearchResultsAfterMillis;
|
return myExpireSearchResultsAfterMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the maximum number of results to return in a GetTags query (DSTU1 only)
|
* Gets the maximum number of results to return in a GetTags query (DSTU1 only)
|
||||||
*/
|
*/
|
||||||
public int getHardTagListLimit() {
|
public int getHardTagListLimit() {
|
||||||
return myHardTagListLimit;
|
return myHardTagListLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIncludeLimit() {
|
public int getIncludeLimit() {
|
||||||
return myIncludeLimit;
|
return myIncludeLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the interceptors which will be notified of operations.
|
* Returns the interceptors which will be notified of operations.
|
||||||
*
|
*
|
||||||
* @see #setInterceptors(List)
|
* @see #setInterceptors(List)
|
||||||
* @deprecated As of 2.2 this method is deprecated. There is no good reason to register an interceptor
|
* @deprecated As of 2.2 this method is deprecated. There is no good reason to register an interceptor
|
||||||
* with the DaoConfig and not with the server via {@link RestfulServer#registerInterceptor(IServerInterceptor)}
|
* with the DaoConfig and not with the server via {@link RestfulServer#registerInterceptor(IServerInterceptor)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public List<IServerInterceptor> getInterceptors() {
|
public List<IServerInterceptor> getInterceptors() {
|
||||||
@ -135,22 +139,26 @@ public class DaoConfig {
|
|||||||
}
|
}
|
||||||
return myInterceptors;
|
return myInterceptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link #setMaximumExpansionSize(int)}
|
* See {@link #setMaximumExpansionSize(int)}
|
||||||
*/
|
*/
|
||||||
public int getMaximumExpansionSize() {
|
public int getMaximumExpansionSize() {
|
||||||
return myMaximumExpansionSize;
|
return myMaximumExpansionSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceEncodingEnum getResourceEncoding() {
|
public ResourceEncodingEnum getResourceEncoding() {
|
||||||
return myResourceEncoding;
|
return myResourceEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSubscriptionPollDelay() {
|
public long getSubscriptionPollDelay() {
|
||||||
return mySubscriptionPollDelay;
|
return mySubscriptionPollDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getSubscriptionPurgeInactiveAfterMillis() {
|
public Long getSubscriptionPurgeInactiveAfterMillis() {
|
||||||
return mySubscriptionPurgeInactiveAfterMillis;
|
return mySubscriptionPurgeInactiveAfterMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This setting may be used to advise the server that any references found in
|
* This setting may be used to advise the server that any references found in
|
||||||
* resources that have any of the base URLs given here will be replaced with
|
* resources that have any of the base URLs given here will be replaced with
|
||||||
@ -165,6 +173,7 @@ public class DaoConfig {
|
|||||||
public Set<String> getTreatBaseUrlsAsLocal() {
|
public Set<String> getTreatBaseUrlsAsLocal() {
|
||||||
return myTreatBaseUrlsAsLocal;
|
return myTreatBaseUrlsAsLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to <code>true</code> (default is <code>false</code>) the server will allow
|
* If set to <code>true</code> (default is <code>false</code>) the server will allow
|
||||||
* resources to have references to external servers. For example if this server is
|
* resources to have references to external servers. For example if this server is
|
||||||
@ -179,7 +188,7 @@ public class DaoConfig {
|
|||||||
* <p>
|
* <p>
|
||||||
* Note that external references will be indexed by the server and may be searched
|
* Note that external references will be indexed by the server and may be searched
|
||||||
* (e.g. <code>Patient:organization</code>), but
|
* (e.g. <code>Patient:organization</code>), but
|
||||||
* chained searches (e.g. <code>Patient:organization.name</code>) will not work across
|
* chained searches (e.g. <code>Patient:organization.name</code>) will not work across
|
||||||
* these references.
|
* these references.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
@ -193,19 +202,37 @@ public class DaoConfig {
|
|||||||
public boolean isAllowExternalReferences() {
|
public boolean isAllowExternalReferences() {
|
||||||
return myAllowExternalReferences;
|
return myAllowExternalReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #setAllowInlineMatchUrlReferences(boolean)
|
* @see #setAllowInlineMatchUrlReferences(boolean)
|
||||||
*/
|
*/
|
||||||
public boolean isAllowInlineMatchUrlReferences() {
|
public boolean isAllowInlineMatchUrlReferences() {
|
||||||
return myAllowInlineMatchUrlReferences;
|
return myAllowInlineMatchUrlReferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAllowMultipleDelete() {
|
public boolean isAllowMultipleDelete() {
|
||||||
return myAllowMultipleDelete;
|
return myAllowMultipleDelete;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
|
* If set to {@code true} the default search params (i.e. the search parameters that are
|
||||||
* task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
|
* defined by the FHIR specification itself) may be overridden by uploading search
|
||||||
|
* parameters to the server with the same code as the built-in search parameter.
|
||||||
|
* <p>
|
||||||
|
* This can be useful if you want to be able to disable or alter
|
||||||
|
* the behaviour of the default search parameters.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The default value for this setting is {@code false}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public boolean isDefaultSearchParamsCanBeOverridden() {
|
||||||
|
return myDefaultSearchParamsCanBeOverridden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
|
||||||
|
* task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
|
||||||
* <p>
|
* <p>
|
||||||
* This feature is useful if you want to define your own process for deleting these (e.g. because
|
* This feature is useful if you want to define your own process for deleting these (e.g. because
|
||||||
* you are running in a cluster)
|
* you are running in a cluster)
|
||||||
@ -217,7 +244,7 @@ public class DaoConfig {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Should contained IDs be indexed the same way that non-contained IDs are (default is
|
* Should contained IDs be indexed the same way that non-contained IDs are (default is
|
||||||
* <code>true</code>)
|
* <code>true</code>)
|
||||||
*/
|
*/
|
||||||
public boolean isIndexContainedResources() {
|
public boolean isIndexContainedResources() {
|
||||||
return myIndexContainedResources;
|
return myIndexContainedResources;
|
||||||
@ -248,7 +275,7 @@ public class DaoConfig {
|
|||||||
* <p>
|
* <p>
|
||||||
* Note that external references will be indexed by the server and may be searched
|
* Note that external references will be indexed by the server and may be searched
|
||||||
* (e.g. <code>Patient:organization</code>), but
|
* (e.g. <code>Patient:organization</code>), but
|
||||||
* chained searches (e.g. <code>Patient:organization.name</code>) will not work across
|
* chained searches (e.g. <code>Patient:organization.name</code>) will not work across
|
||||||
* these references.
|
* these references.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
@ -271,6 +298,7 @@ public class DaoConfig {
|
|||||||
* <p>
|
* <p>
|
||||||
* Default is false for now, as this is an experimental feature.
|
* Default is false for now, as this is an experimental feature.
|
||||||
* </p>
|
* </p>
|
||||||
|
*
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public void setAllowInlineMatchUrlReferences(boolean theAllowInlineMatchUrlReferences) {
|
public void setAllowInlineMatchUrlReferences(boolean theAllowInlineMatchUrlReferences) {
|
||||||
@ -281,6 +309,22 @@ public class DaoConfig {
|
|||||||
myAllowMultipleDelete = theAllowMultipleDelete;
|
myAllowMultipleDelete = theAllowMultipleDelete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to {@code true} the default search params (i.e. the search parameters that are
|
||||||
|
* defined by the FHIR specification itself) may be overridden by uploading search
|
||||||
|
* parameters to the server with the same code as the built-in search parameter.
|
||||||
|
* <p>
|
||||||
|
* This can be useful if you want to be able to disable or alter
|
||||||
|
* the behaviour of the default search parameters.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The default value for this setting is {@code false}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public void setDefaultSearchParamsCanBeOverridden(boolean theDefaultSearchParamsCanBeOverridden) {
|
||||||
|
myDefaultSearchParamsCanBeOverridden = theDefaultSearchParamsCanBeOverridden;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a code system is added that contains more than this number of codes,
|
* When a code system is added that contains more than this number of codes,
|
||||||
* the code system will be indexed later in an incremental process in order to
|
* the code system will be indexed later in an incremental process in order to
|
||||||
@ -294,8 +338,8 @@ public class DaoConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
|
* If this is set to <code>false</code> (default is <code>true</code>) the stale search deletion
|
||||||
* task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
|
* task will be disabled (meaning that search results will be retained in the database indefinitely). USE WITH CAUTION.
|
||||||
* <p>
|
* <p>
|
||||||
* This feature is useful if you want to define your own process for deleting these (e.g. because
|
* This feature is useful if you want to define your own process for deleting these (e.g. because
|
||||||
* you are running in a cluster)
|
* you are running in a cluster)
|
||||||
@ -306,17 +350,18 @@ public class DaoConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the number of milliseconds that search results for a given client search
|
* Sets the number of milliseconds that search results for a given client search
|
||||||
* should be preserved before being purged from the database.
|
* should be preserved before being purged from the database.
|
||||||
* <p>
|
* <p>
|
||||||
* Search results are stored in the database so that they can be paged over multiple
|
* Search results are stored in the database so that they can be paged over multiple
|
||||||
* requests. After this
|
* requests. After this
|
||||||
* number of milliseconds, they will be deleted from the database, and any paging links
|
* number of milliseconds, they will be deleted from the database, and any paging links
|
||||||
* (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
|
* (next/prev links in search response bundles) will become invalid. Defaults to 1 hour.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @see To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
|
* @see To disable this feature entirely, see {@link #setExpireSearchResults(boolean)}
|
||||||
* </p>
|
* </p>
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public void setExpireSearchResultsAfterMillis(long theExpireSearchResultsAfterMillis) {
|
public void setExpireSearchResultsAfterMillis(long theExpireSearchResultsAfterMillis) {
|
||||||
@ -329,7 +374,7 @@ public class DaoConfig {
|
|||||||
* paging provider instead.
|
* paging provider instead.
|
||||||
*
|
*
|
||||||
* @deprecated This method does not do anything. Configure the page size on your
|
* @deprecated This method does not do anything. Configure the page size on your
|
||||||
* paging provider instead. Deprecated in HAPI FHIR 2.3 (Jan 2017)
|
* paging provider instead. Deprecated in HAPI FHIR 2.3 (Jan 2017)
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setHardSearchLimit(@SuppressWarnings("unused") int theHardSearchLimit) {
|
public void setHardSearchLimit(@SuppressWarnings("unused") int theHardSearchLimit) {
|
||||||
@ -354,7 +399,7 @@ public class DaoConfig {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Should contained IDs be indexed the same way that non-contained IDs are (default is
|
* Should contained IDs be indexed the same way that non-contained IDs are (default is
|
||||||
* <code>true</code>)
|
* <code>true</code>)
|
||||||
*/
|
*/
|
||||||
public void setIndexContainedResources(boolean theIndexContainedResources) {
|
public void setIndexContainedResources(boolean theIndexContainedResources) {
|
||||||
myIndexContainedResources = theIndexContainedResources;
|
myIndexContainedResources = theIndexContainedResources;
|
||||||
@ -362,8 +407,9 @@ public class DaoConfig {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This may be used to optionally register server interceptors directly against the DAOs.
|
* This may be used to optionally register server interceptors directly against the DAOs.
|
||||||
|
*
|
||||||
* @deprecated As of 2.2 this method is deprecated. There is no good reason to register an interceptor
|
* @deprecated As of 2.2 this method is deprecated. There is no good reason to register an interceptor
|
||||||
* with the DaoConfig and not with the server via {@link RestfulServer#registerInterceptor(IServerInterceptor)}
|
* with the DaoConfig and not with the server via {@link RestfulServer#registerInterceptor(IServerInterceptor)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setInterceptors(IServerInterceptor... theInterceptor) {
|
public void setInterceptors(IServerInterceptor... theInterceptor) {
|
||||||
@ -375,8 +421,9 @@ public class DaoConfig {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This may be used to optionally register server interceptors directly against the DAOs.
|
* This may be used to optionally register server interceptors directly against the DAOs.
|
||||||
|
*
|
||||||
* @deprecated As of 2.2 this method is deprecated. There is no good reason to register an interceptor
|
* @deprecated As of 2.2 this method is deprecated. There is no good reason to register an interceptor
|
||||||
* with the DaoConfig and not with the server via {@link RestfulServer#registerInterceptor(IServerInterceptor)}
|
* with the DaoConfig and not with the server via {@link RestfulServer#registerInterceptor(IServerInterceptor)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setInterceptors(List<IServerInterceptor> theInterceptors) {
|
public void setInterceptors(List<IServerInterceptor> theInterceptors) {
|
||||||
@ -419,11 +466,11 @@ public class DaoConfig {
|
|||||||
}
|
}
|
||||||
mySubscriptionPurgeInactiveAfterMillis = theMillis;
|
mySubscriptionPurgeInactiveAfterMillis = theMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSubscriptionPurgeInactiveAfterSeconds(int theSeconds) {
|
public void setSubscriptionPurgeInactiveAfterSeconds(int theSeconds) {
|
||||||
setSubscriptionPurgeInactiveAfterMillis(theSeconds * DateUtils.MILLIS_PER_SECOND);
|
setSubscriptionPurgeInactiveAfterMillis(theSeconds * DateUtils.MILLIS_PER_SECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This setting may be used to advise the server that any references found in
|
* This setting may be used to advise the server that any references found in
|
||||||
* resources that have any of the base URLs given here will be replaced with
|
* resources that have any of the base URLs given here will be replaced with
|
||||||
@ -435,8 +482,9 @@ public class DaoConfig {
|
|||||||
* convert this reference to <code>Patient/1</code>
|
* convert this reference to <code>Patient/1</code>
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theTreatBaseUrlsAsLocal The set of base URLs. May be <code>null</code>, which
|
* @param theTreatBaseUrlsAsLocal
|
||||||
* means no references will be treated as external
|
* The set of base URLs. May be <code>null</code>, which
|
||||||
|
* means no references will be treated as external
|
||||||
*/
|
*/
|
||||||
public void setTreatBaseUrlsAsLocal(Set<String> theTreatBaseUrlsAsLocal) {
|
public void setTreatBaseUrlsAsLocal(Set<String> theTreatBaseUrlsAsLocal) {
|
||||||
HashSet<String> treatBaseUrlsAsLocal = new HashSet<String>();
|
HashSet<String> treatBaseUrlsAsLocal = new HashSet<String>();
|
||||||
|
@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
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.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
@ -46,6 +47,9 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISearchParamRegistry mySerarchParamRegistry;
|
||||||
|
|
||||||
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
||||||
SearchParameterMap paramMap = new SearchParameterMap();
|
SearchParameterMap paramMap = new SearchParameterMap();
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
@ -65,7 +69,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
|
|||||||
paramMap.add("_id", new StringParam(theId.getIdPart()));
|
paramMap.add("_id", new StringParam(theId.getIdPart()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao, myTerminologySvc);
|
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao, myTerminologySvc, mySerarchParamRegistry);
|
||||||
builder.setType(getResourceType(), getResourceName());
|
builder.setType(getResourceType(), getResourceName());
|
||||||
return builder.search(paramMap);
|
return builder.search(paramMap);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
|
|
||||||
|
public interface ISearchParamRegistry {
|
||||||
|
|
||||||
|
Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName);
|
||||||
|
|
||||||
|
void forceRefresh();
|
||||||
|
|
||||||
|
}
|
@ -41,6 +41,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
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.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
@ -95,10 +96,12 @@ public class SearchBuilder {
|
|||||||
private IFulltextSearchSvc mySearchDao;
|
private IFulltextSearchSvc mySearchDao;
|
||||||
private Search mySearchEntity;
|
private Search mySearchEntity;
|
||||||
private ISearchResultDao mySearchResultDao;
|
private ISearchResultDao mySearchResultDao;
|
||||||
|
private ISearchParamRegistry mySerarchParamRegistry;
|
||||||
|
|
||||||
private IHapiTerminologySvc myTerminologySvc;
|
private IHapiTerminologySvc myTerminologySvc;
|
||||||
|
|
||||||
public SearchBuilder(FhirContext theFhirContext, EntityManager theEntityManager, PlatformTransactionManager thePlatformTransactionManager, IFulltextSearchSvc theSearchDao, ISearchResultDao theSearchResultDao, BaseHapiFhirDao<?> theDao,
|
public SearchBuilder(FhirContext theFhirContext, EntityManager theEntityManager, PlatformTransactionManager thePlatformTransactionManager, IFulltextSearchSvc theSearchDao, ISearchResultDao theSearchResultDao, BaseHapiFhirDao<?> theDao,
|
||||||
IResourceIndexedSearchParamUriDao theResourceIndexedSearchParamUriDao, IForcedIdDao theForcedIdDao, IHapiTerminologySvc theTerminologySvc) {
|
IResourceIndexedSearchParamUriDao theResourceIndexedSearchParamUriDao, IForcedIdDao theForcedIdDao, IHapiTerminologySvc theTerminologySvc, ISearchParamRegistry theSearchParamRegistry) {
|
||||||
myContext = theFhirContext;
|
myContext = theFhirContext;
|
||||||
myEntityManager = theEntityManager;
|
myEntityManager = theEntityManager;
|
||||||
myPlatformTransactionManager = thePlatformTransactionManager;
|
myPlatformTransactionManager = thePlatformTransactionManager;
|
||||||
@ -108,6 +111,7 @@ public class SearchBuilder {
|
|||||||
myResourceIndexedSearchParamUriDao = theResourceIndexedSearchParamUriDao;
|
myResourceIndexedSearchParamUriDao = theResourceIndexedSearchParamUriDao;
|
||||||
myForcedIdDao = theForcedIdDao;
|
myForcedIdDao = theForcedIdDao;
|
||||||
myTerminologySvc = theTerminologySvc;
|
myTerminologySvc = theTerminologySvc;
|
||||||
|
mySerarchParamRegistry = theSearchParamRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPredicateComposite(RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd) {
|
private void addPredicateComposite(RuntimeSearchParam theParamDef, List<? extends IQueryParameterType> theNextAnd) {
|
||||||
@ -1380,45 +1384,10 @@ public class SearchBuilder {
|
|||||||
return singleCode;
|
return singleCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String determineSystemIfMissing(String theParamName, String code, String system) {
|
|
||||||
if (system == null) {
|
|
||||||
RuntimeSearchParam param = getSearchParam(theParamName);
|
|
||||||
if (param != null) {
|
|
||||||
Set<String> valueSetUris = Sets.newHashSet();
|
|
||||||
for (String nextPath : param.getPathsSplit()) {
|
|
||||||
BaseRuntimeChildDefinition def = myContext.newTerser().getDefinition(myResourceType, nextPath);
|
|
||||||
if (def instanceof BaseRuntimeDeclaredChildDefinition) {
|
|
||||||
String valueSet = ((BaseRuntimeDeclaredChildDefinition) def).getBindingValueSet();
|
|
||||||
if (isNotBlank(valueSet)) {
|
|
||||||
valueSetUris.add(valueSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (valueSetUris.size() == 1) {
|
|
||||||
List<VersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSet(valueSetUris.iterator().next());
|
|
||||||
for (VersionIndependentConcept nextCandidate : candidateCodes) {
|
|
||||||
if (nextCandidate.getCode().equals(code)) {
|
|
||||||
system = nextCandidate.getSystem();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return system;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Predicate createResourceLinkPathPredicate(String theParamName, Root<? extends ResourceLink> from) {
|
private Predicate createResourceLinkPathPredicate(String theParamName, Root<? extends ResourceLink> from) {
|
||||||
return createResourceLinkPathPredicate(myContext, theParamName, from, myResourceType);
|
return createResourceLinkPathPredicate(myContext, theParamName, from, myResourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Predicate createResourceLinkPathPredicate(FhirContext theContext, String theParamName, Root<? extends ResourceLink> from, Class<? extends IBaseResource> resourceType) {
|
|
||||||
RuntimeSearchParam param = theContext.getResourceDefinition(resourceType).getSearchParam(theParamName);
|
|
||||||
List<String> path = param.getPathsSplit();
|
|
||||||
Predicate type = from.get("mySourcePath").in(path);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TypedQuery<Long> createSearchAllByTypeQuery(DateRangeParam theLastUpdated) {
|
private TypedQuery<Long> createSearchAllByTypeQuery(DateRangeParam theLastUpdated) {
|
||||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||||
@ -1532,10 +1501,32 @@ public class SearchBuilder {
|
|||||||
createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
createSort(theBuilder, theFrom, theSort.getChain(), theOrders, thePredicates);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RuntimeSearchParam getSearchParam(String theParamName) {
|
private String determineSystemIfMissing(String theParamName, String code, String system) {
|
||||||
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceType);
|
if (system == null) {
|
||||||
RuntimeSearchParam param = resourceDef.getSearchParam(theParamName);
|
RuntimeSearchParam param = getSearchParam(theParamName);
|
||||||
return param;
|
if (param != null) {
|
||||||
|
Set<String> valueSetUris = Sets.newHashSet();
|
||||||
|
for (String nextPath : param.getPathsSplit()) {
|
||||||
|
BaseRuntimeChildDefinition def = myContext.newTerser().getDefinition(myResourceType, nextPath);
|
||||||
|
if (def instanceof BaseRuntimeDeclaredChildDefinition) {
|
||||||
|
String valueSet = ((BaseRuntimeDeclaredChildDefinition) def).getBindingValueSet();
|
||||||
|
if (isNotBlank(valueSet)) {
|
||||||
|
valueSetUris.add(valueSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valueSetUris.size() == 1) {
|
||||||
|
List<VersionIndependentConcept> candidateCodes = myTerminologySvc.expandValueSet(valueSetUris.iterator().next());
|
||||||
|
for (VersionIndependentConcept nextCandidate : candidateCodes) {
|
||||||
|
if (nextCandidate.getCode().equals(code)) {
|
||||||
|
system = nextCandidate.getSystem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return system;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Long> doGetPids() {
|
public Set<Long> doGetPids() {
|
||||||
@ -1621,6 +1612,12 @@ public class SearchBuilder {
|
|||||||
doSetPids(resultList);
|
doSetPids(resultList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RuntimeSearchParam getSearchParam(String theParamName) {
|
||||||
|
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceType);
|
||||||
|
RuntimeSearchParam param = resourceDef.getSearchParam(theParamName);
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
private void loadResourcesByPid(Collection<Long> theIncludePids, List<IBaseResource> theResourceListToPopulate, Set<Long> theRevIncludedPids, boolean theForHistoryOperation) {
|
private void loadResourcesByPid(Collection<Long> theIncludePids, List<IBaseResource> theResourceListToPopulate, Set<Long> theRevIncludedPids, boolean theForHistoryOperation) {
|
||||||
EntityManager entityManager = myEntityManager;
|
EntityManager entityManager = myEntityManager;
|
||||||
FhirContext context = myContext;
|
FhirContext context = myContext;
|
||||||
@ -1820,7 +1817,8 @@ public class SearchBuilder {
|
|||||||
|
|
||||||
doInitializeSearch();
|
doInitializeSearch();
|
||||||
|
|
||||||
RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceType);
|
// RuntimeResourceDefinition resourceDef = myContext.getResourceDefinition(myResourceType);
|
||||||
|
Map<String, RuntimeSearchParam> searchParams = mySerarchParamRegistry.getActiveSearchParams(myResourceName);
|
||||||
|
|
||||||
for (Entry<String, List<List<? extends IQueryParameterType>>> nextParamEntry : params.entrySet()) {
|
for (Entry<String, List<List<? extends IQueryParameterType>>> nextParamEntry : params.entrySet()) {
|
||||||
String nextParamName = nextParamEntry.getKey();
|
String nextParamName = nextParamEntry.getKey();
|
||||||
@ -1875,7 +1873,7 @@ public class SearchBuilder {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
RuntimeSearchParam nextParamDef = resourceDef.getSearchParam(nextParamName);
|
RuntimeSearchParam nextParamDef = searchParams.get(nextParamName);
|
||||||
if (nextParamDef != null) {
|
if (nextParamDef != null) {
|
||||||
switch (nextParamDef.getParamType()) {
|
switch (nextParamDef.getParamType()) {
|
||||||
case DATE:
|
case DATE:
|
||||||
@ -1953,7 +1951,7 @@ public class SearchBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(Class<? extends IBaseResource> theResourceType, String theResourceName) {
|
public void setType(Class<? extends IBaseResource> theResourceType, String theResourceName) {
|
||||||
myResourceType = theResourceType;
|
myResourceType = theResourceType;
|
||||||
myResourceName = theResourceName;
|
myResourceName = theResourceName;
|
||||||
@ -2044,6 +2042,13 @@ public class SearchBuilder {
|
|||||||
return likeExpression.replace("%", "[%]") + "%";
|
return likeExpression.replace("%", "[%]") + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Predicate createResourceLinkPathPredicate(FhirContext theContext, String theParamName, Root<? extends ResourceLink> from, Class<? extends IBaseResource> resourceType) {
|
||||||
|
RuntimeSearchParam param = theContext.getResourceDefinition(resourceType).getSearchParam(theParamName);
|
||||||
|
List<String> path = param.getPathsSplit();
|
||||||
|
Predicate type = from.get("mySourcePath").in(path);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<Long> filterResourceIdsByLastUpdated(EntityManager theEntityManager, final DateRangeParam theLastUpdated, Collection<Long> thePids) {
|
private static List<Long> filterResourceIdsByLastUpdated(EntityManager theEntityManager, final DateRangeParam theLastUpdated, Collection<Long> thePids) {
|
||||||
CriteriaBuilder builder = theEntityManager.getCriteriaBuilder();
|
CriteriaBuilder builder = theEntityManager.getCriteriaBuilder();
|
||||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||||
|
@ -25,6 +25,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -38,8 +39,6 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
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.jpa.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||||
@ -79,8 +78,8 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamDate> retVal = new HashSet<ResourceIndexedSearchParamDate>();
|
HashSet<ResourceIndexedSearchParamDate> retVal = new HashSet<ResourceIndexedSearchParamDate>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.DATE) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.DATE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -130,12 +129,13 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
|
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.NUMBER) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.NUMBER) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -229,8 +229,8 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
|
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.QUANTITY) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.QUANTITY) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -277,8 +277,8 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
|
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -363,8 +363,8 @@ public class SearchParamExtractorDstu1 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<BaseResourceIndexedSearchParam> retVal = new HashSet<BaseResourceIndexedSearchParam>();
|
HashSet<BaseResourceIndexedSearchParam> retVal = new HashSet<BaseResourceIndexedSearchParam>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -120,8 +121,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamDate> retVal = new HashSet<ResourceIndexedSearchParamDate>();
|
HashSet<ResourceIndexedSearchParamDate> retVal = new HashSet<ResourceIndexedSearchParamDate>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.DATE) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.DATE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -181,8 +182,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
|
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.NUMBER) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.NUMBER) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -281,8 +282,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
|
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.QUANTITY) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.QUANTITY) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -335,23 +336,25 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
|
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
String resourceName = getContext().getResourceDefinition(theResource).getName();
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
|
||||||
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String nextPath = nextSpDef.getPath();
|
String nextPath = nextSpDef.getPath();
|
||||||
String resourceName = nextSpDef.getName();
|
String nextSpName = nextSpDef.getName();
|
||||||
|
|
||||||
if (isBlank(nextPath)) {
|
if (isBlank(nextPath)) {
|
||||||
|
|
||||||
// TODO: implement phonetic, and any others that have no path
|
// TODO: implement phonetic, and any others that have no path
|
||||||
|
|
||||||
if ("Questionnaire".equals(def.getName()) && nextSpDef.getName().equals("title")) {
|
if ("Questionnaire".equals(resourceName) && nextSpDef.getName().equals("title")) {
|
||||||
Questionnaire q = (Questionnaire) theResource;
|
Questionnaire q = (Questionnaire) theResource;
|
||||||
String title = q.getGroup().getTitle();
|
String title = q.getGroup().getTitle();
|
||||||
addSearchTerm(theEntity, retVal, resourceName, title);
|
addSearchTerm(theEntity, retVal, nextSpName, title);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -369,7 +372,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
if (nextObject instanceof IPrimitiveDatatype<?>) {
|
if (nextObject instanceof IPrimitiveDatatype<?>) {
|
||||||
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
|
IPrimitiveDatatype<?> nextValue = (IPrimitiveDatatype<?>) nextObject;
|
||||||
String searchTerm = nextValue.getValueAsString();
|
String searchTerm = nextValue.getValueAsString();
|
||||||
addSearchTerm(theEntity, retVal, resourceName, searchTerm);
|
addSearchTerm(theEntity, retVal, nextSpName, searchTerm);
|
||||||
} else {
|
} else {
|
||||||
if (nextObject instanceof BaseHumanNameDt) {
|
if (nextObject instanceof BaseHumanNameDt) {
|
||||||
ArrayList<StringDt> allNames = new ArrayList<StringDt>();
|
ArrayList<StringDt> allNames = new ArrayList<StringDt>();
|
||||||
@ -377,7 +380,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
allNames.addAll(nextHumanName.getFamily());
|
allNames.addAll(nextHumanName.getFamily());
|
||||||
allNames.addAll(nextHumanName.getGiven());
|
allNames.addAll(nextHumanName.getGiven());
|
||||||
for (StringDt nextName : allNames) {
|
for (StringDt nextName : allNames) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, nextName.getValue());
|
addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
|
||||||
}
|
}
|
||||||
} else if (nextObject instanceof AddressDt) {
|
} else if (nextObject instanceof AddressDt) {
|
||||||
ArrayList<StringDt> allNames = new ArrayList<StringDt>();
|
ArrayList<StringDt> allNames = new ArrayList<StringDt>();
|
||||||
@ -388,16 +391,16 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
allNames.add(nextAddress.getCountryElement());
|
allNames.add(nextAddress.getCountryElement());
|
||||||
allNames.add(nextAddress.getPostalCodeElement());
|
allNames.add(nextAddress.getPostalCodeElement());
|
||||||
for (StringDt nextName : allNames) {
|
for (StringDt nextName : allNames) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, nextName.getValue());
|
addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
|
||||||
}
|
}
|
||||||
} else if (nextObject instanceof ContactPointDt) {
|
} else if (nextObject instanceof ContactPointDt) {
|
||||||
ContactPointDt nextContact = (ContactPointDt) nextObject;
|
ContactPointDt nextContact = (ContactPointDt) nextObject;
|
||||||
if (nextContact.getValueElement().isEmpty() == false) {
|
if (nextContact.getValueElement().isEmpty() == false) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, nextContact.getValue());
|
addSearchTerm(theEntity, retVal, nextSpName, nextContact.getValue());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!multiType) {
|
if (!multiType) {
|
||||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
throw new ConfigurationException("Search param " + nextSpName + " is of unexpected datatype: " + nextObject.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,8 +426,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
useSystem = vs.getCodeSystem().getSystem();
|
useSystem = vs.getCodeSystem().getSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -575,8 +578,8 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<ResourceIndexedSearchParamUri>();
|
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<ResourceIndexedSearchParamUri>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.URI) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.URI) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -622,6 +625,7 @@ public class SearchParamExtractorDstu2 extends BaseSearchParamExtractor implemen
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
|
private void extractTokensFromCodeableConcept(List<String> theSystems, List<String> theCodes, CodeableConceptDt theCodeableConcept, ResourceTable theEntity, Set<BaseResourceIndexedSearchParam> theListToPopulate, RuntimeSearchParam theParameterDef) {
|
||||||
for (CodingDt nextCoding : theCodeableConcept.getCoding()) {
|
for (CodingDt nextCoding : theCodeableConcept.getCoding()) {
|
||||||
extractTokensFromCoding(theSystems, theCodes, theEntity, theListToPopulate, theParameterDef, nextCoding);
|
extractTokensFromCoding(theSystems, theCodes, theEntity, theListToPopulate, theParameterDef, nextCoding);
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
public class SearchParamRegistryDstu1 extends BaseSearchParamRegistry {
|
||||||
|
// nothing yet
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao;
|
||||||
|
|
||||||
|
public class SearchParamRegistryDstu2 extends BaseSearchParamRegistry {
|
||||||
|
// nothing yet
|
||||||
|
|
||||||
|
}
|
@ -27,8 +27,10 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
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.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoPatient;
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoPatient;
|
||||||
|
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
import ca.uhn.fhir.jpa.dao.SearchBuilder;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
|
||||||
@ -45,6 +47,9 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetai
|
|||||||
|
|
||||||
public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>implements IFhirResourceDaoPatient<Patient> {
|
public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>implements IFhirResourceDaoPatient<Patient> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISearchParamRegistry mySerarchParamRegistry;
|
||||||
|
|
||||||
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
|
||||||
SearchParameterMap paramMap = new SearchParameterMap();
|
SearchParameterMap paramMap = new SearchParameterMap();
|
||||||
if (theCount != null) {
|
if (theCount != null) {
|
||||||
@ -64,7 +69,7 @@ public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>im
|
|||||||
paramMap.add("_id", new StringParam(theId.getIdPart()));
|
paramMap.add("_id", new StringParam(theId.getIdPart()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao, myTerminologySvc);
|
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao, myTerminologySvc, mySerarchParamRegistry);
|
||||||
builder.setType(getResourceType(), getResourceName());
|
builder.setType(getResourceType(), getResourceName());
|
||||||
return builder.search(paramMap);
|
return builder.search(paramMap);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -56,7 +57,6 @@ import org.hl7.fhir.dstu3.model.Location.LocationPositionComponent;
|
|||||||
import org.hl7.fhir.dstu3.model.Patient.PatientCommunicationComponent;
|
import org.hl7.fhir.dstu3.model.Patient.PatientCommunicationComponent;
|
||||||
import org.hl7.fhir.dstu3.model.Period;
|
import org.hl7.fhir.dstu3.model.Period;
|
||||||
import org.hl7.fhir.dstu3.model.Quantity;
|
import org.hl7.fhir.dstu3.model.Quantity;
|
||||||
import org.hl7.fhir.dstu3.model.Questionnaire;
|
|
||||||
import org.hl7.fhir.dstu3.model.Range;
|
import org.hl7.fhir.dstu3.model.Range;
|
||||||
import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
@ -73,11 +73,11 @@ import com.google.common.annotations.VisibleForTesting;
|
|||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
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.jpa.dao.BaseHapiFhirDao;
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor;
|
import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor;
|
||||||
import ca.uhn.fhir.jpa.dao.ISearchParamExtractor;
|
import ca.uhn.fhir.jpa.dao.ISearchParamExtractor;
|
||||||
|
import ca.uhn.fhir.jpa.dao.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.jpa.dao.PathAndRef;
|
import ca.uhn.fhir.jpa.dao.PathAndRef;
|
||||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamCoords;
|
||||||
@ -97,7 +97,7 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private org.hl7.fhir.dstu3.hapi.validation.IValidationSupport myValidationSupport;
|
private org.hl7.fhir.dstu3.hapi.validation.IValidationSupport myValidationSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@ -105,8 +105,8 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchParamExtractorDstu3(FhirContext theCtx, IValidationSupport theValidationSupport) {
|
public SearchParamExtractorDstu3(FhirContext theCtx, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry) {
|
||||||
super(theCtx);
|
super(theCtx, theSearchParamRegistry);
|
||||||
myValidationSupport = theValidationSupport;
|
myValidationSupport = theValidationSupport;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,8 +147,8 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamDate> retVal = new HashSet<ResourceIndexedSearchParamDate>();
|
HashSet<ResourceIndexedSearchParamDate> retVal = new HashSet<ResourceIndexedSearchParamDate>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.DATE) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.DATE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -226,8 +226,8 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
public HashSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
|
HashSet<ResourceIndexedSearchParamNumber> retVal = new HashSet<ResourceIndexedSearchParamNumber>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.NUMBER) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.NUMBER) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -320,8 +320,8 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
|
HashSet<ResourceIndexedSearchParamQuantity> retVal = new HashSet<ResourceIndexedSearchParamQuantity>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.QUANTITY) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.QUANTITY) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -384,24 +384,28 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
|
HashSet<ResourceIndexedSearchParamString> retVal = new HashSet<ResourceIndexedSearchParamString>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
String resourceName = getContext().getResourceDefinition(theResource).getName();
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
|
||||||
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.STRING) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String nextPath = nextSpDef.getPath();
|
String nextPath = nextSpDef.getPath();
|
||||||
String resourceName = nextSpDef.getName();
|
String nextSpName = nextSpDef.getName();
|
||||||
|
|
||||||
if (isBlank(nextPath)) {
|
if (isBlank(nextPath)) {
|
||||||
|
|
||||||
// TODO: implement phonetic, and any others that have no path
|
// // TODO: implement phonetic, and any others that have no path
|
||||||
|
//
|
||||||
if ("Questionnaire".equals(def.getName()) && nextSpDef.getName().equals("title")) {
|
// // TODO: do we still need this check?
|
||||||
Questionnaire q = (Questionnaire) theResource;
|
// if ("Questionnaire".equals(nextSpName) && nextSpDef.getName().equals("title")) {
|
||||||
String title = "";// q.getGroup().getTitle();
|
// Questionnaire q = (Questionnaire) theResource;
|
||||||
addSearchTerm(theEntity, retVal, resourceName, title);
|
// String title = "";// q.getGroup().getTitle();
|
||||||
}
|
// addSearchTerm(theEntity, retVal, nextSpName, title);
|
||||||
|
// }
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,7 +422,7 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
if (nextObject instanceof IPrimitiveType<?>) {
|
if (nextObject instanceof IPrimitiveType<?>) {
|
||||||
IPrimitiveType<?> nextValue = (IPrimitiveType<?>) nextObject;
|
IPrimitiveType<?> nextValue = (IPrimitiveType<?>) nextObject;
|
||||||
String searchTerm = nextValue.getValueAsString();
|
String searchTerm = nextValue.getValueAsString();
|
||||||
addSearchTerm(theEntity, retVal, resourceName, searchTerm);
|
addSearchTerm(theEntity, retVal, nextSpName, searchTerm);
|
||||||
} else {
|
} else {
|
||||||
if (nextObject instanceof HumanName) {
|
if (nextObject instanceof HumanName) {
|
||||||
ArrayList<StringType> allNames = new ArrayList<StringType>();
|
ArrayList<StringType> allNames = new ArrayList<StringType>();
|
||||||
@ -428,7 +432,7 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
}
|
}
|
||||||
allNames.addAll(nextHumanName.getGiven());
|
allNames.addAll(nextHumanName.getGiven());
|
||||||
for (StringType nextName : allNames) {
|
for (StringType nextName : allNames) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, nextName.getValue());
|
addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
|
||||||
}
|
}
|
||||||
} else if (nextObject instanceof Address) {
|
} else if (nextObject instanceof Address) {
|
||||||
ArrayList<StringType> allNames = new ArrayList<StringType>();
|
ArrayList<StringType> allNames = new ArrayList<StringType>();
|
||||||
@ -439,29 +443,29 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
allNames.add(nextAddress.getCountryElement());
|
allNames.add(nextAddress.getCountryElement());
|
||||||
allNames.add(nextAddress.getPostalCodeElement());
|
allNames.add(nextAddress.getPostalCodeElement());
|
||||||
for (StringType nextName : allNames) {
|
for (StringType nextName : allNames) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, nextName.getValue());
|
addSearchTerm(theEntity, retVal, nextSpName, nextName.getValue());
|
||||||
}
|
}
|
||||||
} else if (nextObject instanceof ContactPoint) {
|
} else if (nextObject instanceof ContactPoint) {
|
||||||
ContactPoint nextContact = (ContactPoint) nextObject;
|
ContactPoint nextContact = (ContactPoint) nextObject;
|
||||||
if (nextContact.getValueElement().isEmpty() == false) {
|
if (nextContact.getValueElement().isEmpty() == false) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, nextContact.getValue());
|
addSearchTerm(theEntity, retVal, nextSpName, nextContact.getValue());
|
||||||
}
|
}
|
||||||
} else if (nextObject instanceof Quantity) {
|
} else if (nextObject instanceof Quantity) {
|
||||||
BigDecimal value = ((Quantity) nextObject).getValue();
|
BigDecimal value = ((Quantity) nextObject).getValue();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, value.toPlainString());
|
addSearchTerm(theEntity, retVal, nextSpName, value.toPlainString());
|
||||||
}
|
}
|
||||||
} else if (nextObject instanceof Range) {
|
} else if (nextObject instanceof Range) {
|
||||||
SimpleQuantity low = ((Range) nextObject).getLow();
|
SimpleQuantity low = ((Range) nextObject).getLow();
|
||||||
if (low != null) {
|
if (low != null) {
|
||||||
BigDecimal value = low.getValue();
|
BigDecimal value = low.getValue();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
addSearchTerm(theEntity, retVal, resourceName, value.toPlainString());
|
addSearchTerm(theEntity, retVal, nextSpName, value.toPlainString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!multiType) {
|
if (!multiType) {
|
||||||
throw new ConfigurationException("Search param " + resourceName + " is of unexpected datatype: " + nextObject.getClass());
|
throw new ConfigurationException("Search param " + nextSpName + " is of unexpected datatype: " + nextObject.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -486,8 +490,8 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
useSystem = cs.getUrl();
|
useSystem = cs.getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.TOKEN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -633,8 +637,8 @@ public class SearchParamExtractorDstu3 extends BaseSearchParamExtractor implemen
|
|||||||
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
|
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(ResourceTable theEntity, IBaseResource theResource) {
|
||||||
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<ResourceIndexedSearchParamUri>();
|
HashSet<ResourceIndexedSearchParamUri> retVal = new HashSet<ResourceIndexedSearchParamUri>();
|
||||||
|
|
||||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||||
for (RuntimeSearchParam nextSpDef : def.getSearchParams()) {
|
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||||
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.URI) {
|
if (nextSpDef.getParamType() != RestSearchParameterTypeEnum.URI) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,194 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
import org.hl7.fhir.dstu3.model.CodeType;
|
||||||
|
import org.hl7.fhir.dstu3.model.SearchParameter;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
|
import ca.uhn.fhir.context.RuntimeSearchParam.RuntimeSearchParamStatusEnum;
|
||||||
|
import ca.uhn.fhir.jpa.dao.BaseSearchParamRegistry;
|
||||||
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||||
|
import ca.uhn.fhir.rest.method.RestSearchParameterTypeEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
|
|
||||||
|
public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchParamRegistryDstu3.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IFhirResourceDao<SearchParameter> mySpDao;
|
||||||
|
|
||||||
|
private long myLastRefresh;
|
||||||
|
|
||||||
|
private volatile Map<String, Map<String, RuntimeSearchParam>> myActiveSearchParams;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DaoConfig myDaoConfig;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
||||||
|
|
||||||
|
long refreshInterval = 60 * DateUtils.MILLIS_PER_MINUTE;
|
||||||
|
if (System.currentTimeMillis() - refreshInterval > myLastRefresh) {
|
||||||
|
StopWatch sw = new StopWatch();
|
||||||
|
|
||||||
|
Map<String, Map<String, RuntimeSearchParam>> searchParams = new HashMap<String, Map<String, RuntimeSearchParam>>();
|
||||||
|
for (Entry<String, Map<String, RuntimeSearchParam>> nextBuiltInEntry : getBuiltInSearchParams().entrySet()) {
|
||||||
|
for (RuntimeSearchParam nextParam : nextBuiltInEntry.getValue().values()) {
|
||||||
|
String nextResourceName = nextBuiltInEntry.getKey();
|
||||||
|
getSearchParamMap(searchParams, nextResourceName).put(nextParam.getName(), nextParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IBundleProvider allSearchParamsBp = mySpDao.search(new SearchParameterMap());
|
||||||
|
int size = allSearchParamsBp.size();
|
||||||
|
|
||||||
|
// Just in case..
|
||||||
|
if (size > 10000) {
|
||||||
|
ourLog.warn("Unable to support >10000 search params!");
|
||||||
|
size = 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<IBaseResource> allSearchParams = allSearchParamsBp.getResources(0, size);
|
||||||
|
for (IBaseResource nextResource : allSearchParams) {
|
||||||
|
SearchParameter nextSp = (SearchParameter) nextResource;
|
||||||
|
RuntimeSearchParam runtimeSp = toRuntimeSp(nextSp);
|
||||||
|
if (runtimeSp == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dotIdx = runtimeSp.getPath().indexOf('.');
|
||||||
|
if (dotIdx == -1) {
|
||||||
|
ourLog.warn("Can not determine resource type of {}", runtimeSp.getPath());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String resourceType = runtimeSp.getPath().substring(0, dotIdx);
|
||||||
|
|
||||||
|
Map<String, RuntimeSearchParam> searchParamMap = getSearchParamMap(searchParams, resourceType);
|
||||||
|
String name = runtimeSp.getName();
|
||||||
|
if (myDaoConfig.isDefaultSearchParamsCanBeOverridden() || !searchParamMap.containsKey(name)) {
|
||||||
|
searchParamMap.put(name, runtimeSp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Map<String, RuntimeSearchParam>> activeSearchParams = new HashMap<String, Map<String, RuntimeSearchParam>>();
|
||||||
|
for (Entry<String, Map<String, RuntimeSearchParam>> nextEntry : searchParams.entrySet()) {
|
||||||
|
for (RuntimeSearchParam nextSp : nextEntry.getValue().values()) {
|
||||||
|
if (nextSp.getStatus() == RuntimeSearchParamStatusEnum.ACTIVE) {
|
||||||
|
if (!activeSearchParams.containsKey(nextEntry.getKey())) {
|
||||||
|
activeSearchParams.put(nextEntry.getKey(), new HashMap<String, RuntimeSearchParam>());
|
||||||
|
}
|
||||||
|
activeSearchParams.get(nextEntry.getKey()).put(nextSp.getName(), nextSp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myActiveSearchParams = activeSearchParams;
|
||||||
|
|
||||||
|
myLastRefresh = System.currentTimeMillis();
|
||||||
|
ourLog.info("Refreshed search parameter cache in {}ms", sw.getMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
return myActiveSearchParams.get(theResourceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void forceRefresh() {
|
||||||
|
myLastRefresh = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, RuntimeSearchParam> getSearchParamMap(Map<String, Map<String, RuntimeSearchParam>> searchParams, String theResourceName) {
|
||||||
|
Map<String, RuntimeSearchParam> retVal = searchParams.get(theResourceName);
|
||||||
|
if (retVal == null) {
|
||||||
|
retVal = new HashMap<String, RuntimeSearchParam>();
|
||||||
|
searchParams.put(theResourceName, retVal);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RuntimeSearchParam toRuntimeSp(SearchParameter theNextSp) {
|
||||||
|
String name = theNextSp.getCode();
|
||||||
|
String description = theNextSp.getDescription();
|
||||||
|
String path = theNextSp.getXpath();
|
||||||
|
RestSearchParameterTypeEnum paramType = null;
|
||||||
|
RuntimeSearchParamStatusEnum status = null;
|
||||||
|
switch (theNextSp.getType()) {
|
||||||
|
case COMPOSITE:
|
||||||
|
paramType = RestSearchParameterTypeEnum.COMPOSITE;
|
||||||
|
break;
|
||||||
|
case DATE:
|
||||||
|
paramType = RestSearchParameterTypeEnum.DATE;
|
||||||
|
break;
|
||||||
|
case NUMBER:
|
||||||
|
paramType = RestSearchParameterTypeEnum.NUMBER;
|
||||||
|
break;
|
||||||
|
case QUANTITY:
|
||||||
|
paramType = RestSearchParameterTypeEnum.QUANTITY;
|
||||||
|
break;
|
||||||
|
case REFERENCE:
|
||||||
|
paramType = RestSearchParameterTypeEnum.REFERENCE;
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
paramType = RestSearchParameterTypeEnum.STRING;
|
||||||
|
break;
|
||||||
|
case TOKEN:
|
||||||
|
paramType = RestSearchParameterTypeEnum.TOKEN;
|
||||||
|
break;
|
||||||
|
case URI:
|
||||||
|
paramType = RestSearchParameterTypeEnum.URI;
|
||||||
|
break;
|
||||||
|
case NULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (theNextSp.getStatus() != null) {
|
||||||
|
switch (theNextSp.getStatus()) {
|
||||||
|
case ACTIVE:
|
||||||
|
status = RuntimeSearchParamStatusEnum.ACTIVE;
|
||||||
|
break;
|
||||||
|
case DRAFT:
|
||||||
|
status = RuntimeSearchParamStatusEnum.DRAFT;
|
||||||
|
break;
|
||||||
|
case RETIRED:
|
||||||
|
status = RuntimeSearchParamStatusEnum.RETIRED;
|
||||||
|
break;
|
||||||
|
case NULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set<String> providesMembershipInCompartments = Collections.emptySet();
|
||||||
|
Set<String> targets = toStrings(theNextSp.getTarget());
|
||||||
|
|
||||||
|
if (isBlank(name) || isBlank(path) || paramType == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuntimeSearchParam retVal = new RuntimeSearchParam(name, description, path, paramType, providesMembershipInCompartments, targets, status);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> toStrings(List<CodeType> theTarget) {
|
||||||
|
HashSet<String> retVal = new HashSet<String>();
|
||||||
|
for (CodeType next : theTarget) {
|
||||||
|
if (isNotBlank(next.getValue())) {
|
||||||
|
retVal.add(next.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -53,6 +53,12 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
|||||||
private static JpaValidationSupportChainDstu3 ourJpaValidationSupportChainDstu3;
|
private static JpaValidationSupportChainDstu3 ourJpaValidationSupportChainDstu3;
|
||||||
private static IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> ourValueSetDao;
|
private static IFhirResourceDaoValueSet<ValueSet, Coding, CodeableConcept> ourValueSetDao;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("mySearchParameterDaoDstu3")
|
||||||
|
protected IFhirResourceDao<SearchParameter> mySearchParameterDao;
|
||||||
|
@Autowired
|
||||||
|
protected ISearchParamRegistry mySearchParamRegsitry;
|
||||||
// @Autowired
|
// @Autowired
|
||||||
// protected HapiWorkerContext myHapiWorkerContext;
|
// protected HapiWorkerContext myHapiWorkerContext;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -0,0 +1,203 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.contains;
|
||||||
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
import static org.hamcrest.Matchers.hasItems;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||||
|
import org.hl7.fhir.dstu3.model.ContactPoint.ContactPointSystem;
|
||||||
|
import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
|
||||||
|
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType;
|
||||||
|
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.codesystems.PublicationStatus;
|
||||||
|
import org.hl7.fhir.dstu3.model.codesystems.SearchParamType;
|
||||||
|
import org.hl7.fhir.instance.model.SearchParameter.XPathUsageType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.jpa.dao.SearchParameterMap.EverythingModeEnum;
|
||||||
|
import ca.uhn.fhir.jpa.entity.*;
|
||||||
|
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvc;
|
||||||
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
|
import ca.uhn.fhir.model.api.Include;
|
||||||
|
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.SortOrderEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.SortSpec;
|
||||||
|
import ca.uhn.fhir.rest.param.*;
|
||||||
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public class FhirResourceDaoDstu3SearchCustomParamTest extends BaseJpaDstu3Test {
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3SearchCustomParamTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithCustomParam() {
|
||||||
|
|
||||||
|
SearchParameter fooSp = new SearchParameter();
|
||||||
|
fooSp.setCode("foo");
|
||||||
|
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||||
|
fooSp.setTitle("FOO SP");
|
||||||
|
fooSp.setXpath("Patient.gender");
|
||||||
|
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||||
|
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
|
||||||
|
mySearchParameterDao.create(fooSp, mySrd);
|
||||||
|
|
||||||
|
mySearchParamRegsitry.forceRefresh();
|
||||||
|
|
||||||
|
Patient pat = new Patient();
|
||||||
|
pat.setGender(AdministrativeGender.MALE);
|
||||||
|
IIdType patId = myPatientDao.create(pat, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Patient pat2 = new Patient();
|
||||||
|
pat.setGender(AdministrativeGender.FEMALE);
|
||||||
|
IIdType patId2 = myPatientDao.create(pat2, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap map;
|
||||||
|
IBundleProvider results;
|
||||||
|
List<String> foundResources;
|
||||||
|
|
||||||
|
//Try with custom gender SP
|
||||||
|
map = new SearchParameterMap();
|
||||||
|
map.add("foo", new TokenParam(null, "male"));
|
||||||
|
results = myPatientDao.search(map);
|
||||||
|
foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(foundResources, contains(patId.getValue()));
|
||||||
|
|
||||||
|
//Try with normal gender SP
|
||||||
|
map = new SearchParameterMap();
|
||||||
|
map.add("gender", new TokenParam(null, "male"));
|
||||||
|
results = myPatientDao.search(map);
|
||||||
|
foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(foundResources, contains(patId.getValue()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithCustomParamDraft() {
|
||||||
|
|
||||||
|
SearchParameter fooSp = new SearchParameter();
|
||||||
|
fooSp.setCode("foo");
|
||||||
|
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||||
|
fooSp.setTitle("FOO SP");
|
||||||
|
fooSp.setXpath("Patient.gender");
|
||||||
|
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||||
|
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.DRAFT);
|
||||||
|
mySearchParameterDao.create(fooSp, mySrd);
|
||||||
|
|
||||||
|
mySearchParamRegsitry.forceRefresh();
|
||||||
|
|
||||||
|
Patient pat = new Patient();
|
||||||
|
pat.setGender(AdministrativeGender.MALE);
|
||||||
|
IIdType patId = myPatientDao.create(pat, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Patient pat2 = new Patient();
|
||||||
|
pat.setGender(AdministrativeGender.FEMALE);
|
||||||
|
IIdType patId2 = myPatientDao.create(pat2, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap map;
|
||||||
|
IBundleProvider results;
|
||||||
|
List<String> foundResources;
|
||||||
|
|
||||||
|
//Try with custom gender SP (should find nothing)
|
||||||
|
map = new SearchParameterMap();
|
||||||
|
map.add("foo", new TokenParam(null, "male"));
|
||||||
|
results = myPatientDao.search(map);
|
||||||
|
foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(foundResources, empty());
|
||||||
|
|
||||||
|
//Try with normal gender SP
|
||||||
|
map = new SearchParameterMap();
|
||||||
|
map.add("gender", new TokenParam(null, "male"));
|
||||||
|
results = myPatientDao.search(map);
|
||||||
|
foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(foundResources, contains(patId.getValue()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithCustomParamNullStatus() {
|
||||||
|
|
||||||
|
SearchParameter fooSp = new SearchParameter();
|
||||||
|
fooSp.setCode("foo");
|
||||||
|
fooSp.setType(org.hl7.fhir.dstu3.model.Enumerations.SearchParamType.TOKEN);
|
||||||
|
fooSp.setTitle("FOO SP");
|
||||||
|
fooSp.setXpath("Patient.gender");
|
||||||
|
fooSp.setXpathUsage(org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType.NORMAL);
|
||||||
|
fooSp.setStatus(null);
|
||||||
|
mySearchParameterDao.create(fooSp, mySrd);
|
||||||
|
|
||||||
|
mySearchParamRegsitry.forceRefresh();
|
||||||
|
|
||||||
|
Patient pat = new Patient();
|
||||||
|
pat.setGender(AdministrativeGender.MALE);
|
||||||
|
IIdType patId = myPatientDao.create(pat, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Patient pat2 = new Patient();
|
||||||
|
pat.setGender(AdministrativeGender.FEMALE);
|
||||||
|
IIdType patId2 = myPatientDao.create(pat2, mySrd).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
SearchParameterMap map;
|
||||||
|
IBundleProvider results;
|
||||||
|
List<String> foundResources;
|
||||||
|
|
||||||
|
//Try with custom gender SP (should find nothing)
|
||||||
|
map = new SearchParameterMap();
|
||||||
|
map.add("foo", new TokenParam(null, "male"));
|
||||||
|
results = myPatientDao.search(map);
|
||||||
|
foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(foundResources, empty());
|
||||||
|
|
||||||
|
//Try with normal gender SP
|
||||||
|
map = new SearchParameterMap();
|
||||||
|
map.add("gender", new TokenParam(null, "male"));
|
||||||
|
results = myPatientDao.search(map);
|
||||||
|
foundResources = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(foundResources, contains(patId.getValue()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
package ca.uhn.fhir.jpa.dao.dstu3;
|
package ca.uhn.fhir.jpa.dao.dstu3;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
|
import org.hl7.fhir.dstu3.hapi.validation.DefaultProfileValidationSupport;
|
||||||
@ -12,6 +14,9 @@ import org.junit.BeforeClass;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
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.jpa.dao.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamToken;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.entity.ResourceTable;
|
||||||
@ -37,7 +42,24 @@ public class SearchParamExtractorDstu3Test {
|
|||||||
Observation obs = new Observation();
|
Observation obs = new Observation();
|
||||||
obs.addCategory().addCoding().setSystem("SYSTEM").setCode("CODE");
|
obs.addCategory().addCoding().setSystem("SYSTEM").setCode("CODE");
|
||||||
|
|
||||||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(ourCtx, ourValidationSupport);
|
ISearchParamRegistry searchParamRegistry = new ISearchParamRegistry() {
|
||||||
|
@Override
|
||||||
|
public Map<String,RuntimeSearchParam> getActiveSearchParams(String theResourceName) {
|
||||||
|
RuntimeResourceDefinition nextResDef = ourCtx.getResourceDefinition(theResourceName);
|
||||||
|
Map<String, RuntimeSearchParam> sps = new HashMap<String, RuntimeSearchParam>();
|
||||||
|
for (RuntimeSearchParam nextSp : nextResDef.getSearchParams()) {
|
||||||
|
sps.put(nextSp.getName(), nextSp);
|
||||||
|
}
|
||||||
|
return sps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void forceRefresh() {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(ourCtx, ourValidationSupport, searchParamRegistry);
|
||||||
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(new ResourceTable(), obs);
|
Set<BaseResourceIndexedSearchParam> tokens = extractor.extractSearchParamTokens(new ResourceTable(), obs);
|
||||||
assertEquals(1, tokens.size());
|
assertEquals(1, tokens.size());
|
||||||
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
|
ResourceIndexedSearchParamToken token = (ResourceIndexedSearchParamToken) tokens.iterator().next();
|
||||||
|
@ -22,6 +22,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
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.RuntimeSearchParam.RuntimeSearchParamStatusEnum;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||||
@ -175,8 +176,8 @@ public class DynamicSearchTest {
|
|||||||
@Override
|
@Override
|
||||||
public List<RuntimeSearchParam> getSearchParameters() {
|
public List<RuntimeSearchParam> getSearchParameters() {
|
||||||
ArrayList<RuntimeSearchParam> retVal = new ArrayList<RuntimeSearchParam>();
|
ArrayList<RuntimeSearchParam> retVal = new ArrayList<RuntimeSearchParam>();
|
||||||
retVal.add(new RuntimeSearchParam("param1", "This is the first parameter", "Patient.param1", RestSearchParameterTypeEnum.STRING, null, null));
|
retVal.add(new RuntimeSearchParam("param1", "This is the first parameter", "Patient.param1", RestSearchParameterTypeEnum.STRING, null, null, RuntimeSearchParamStatusEnum.ACTIVE));
|
||||||
retVal.add(new RuntimeSearchParam("param2", "This is the second parameter", "Patient.param2", RestSearchParameterTypeEnum.DATE, null, null));
|
retVal.add(new RuntimeSearchParam("param2", "This is the second parameter", "Patient.param2", RestSearchParameterTypeEnum.DATE, null, null, RuntimeSearchParamStatusEnum.ACTIVE));
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,261 @@
|
|||||||
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.either;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.dstu3.model.HumanName;
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OptionalParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.RawParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
|
import ca.uhn.fhir.rest.param.StringAndListParam;
|
||||||
|
import ca.uhn.fhir.util.PortUtil;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
|
||||||
|
public class SearchDefaultMethodDstu3Test {
|
||||||
|
|
||||||
|
private static CloseableHttpClient ourClient;
|
||||||
|
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchDefaultMethodDstu3Test.class);
|
||||||
|
private static int ourPort;
|
||||||
|
private static Server ourServer;
|
||||||
|
private static String ourLastMethod;
|
||||||
|
private static StringAndListParam ourLastParam1;
|
||||||
|
private static StringAndListParam ourLastParam2;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() {
|
||||||
|
ourLastMethod = null;
|
||||||
|
ourLastParam1 = null;
|
||||||
|
ourLastParam2 = null;
|
||||||
|
ourLastAdditionalParams = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchNoParams() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertThat(ourLastMethod, either(equalTo("search01")).or(equalTo("search02")));
|
||||||
|
assertEquals(null, ourLastParam1);
|
||||||
|
assertEquals(null, ourLastParam2);
|
||||||
|
assertEquals(null, ourLastAdditionalParams);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchOneOptionalParam() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?param1=val1");
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertEquals("val1", ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
assertEquals(null, ourLastParam2);
|
||||||
|
assertEquals(null, ourLastAdditionalParams);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchTwoOptionalParams() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?param1=val1¶m2=val2");
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertEquals("val1", ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
|
||||||
|
assertThat(ourLastParam2.getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertThat(ourLastParam2.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertEquals("val2", ourLastParam2.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
|
||||||
|
assertEquals(null, ourLastAdditionalParams);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchTwoOptionalParamsAndExtraParam() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?param1=val1¶m2=val2¶m3=val3&_pretty=true");
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertEquals("search03", ourLastMethod);
|
||||||
|
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertEquals("val1", ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
|
||||||
|
assertThat(ourLastParam2.getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertThat(ourLastParam2.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertEquals("val2", ourLastParam2.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
|
||||||
|
ourLog.info(ourLastAdditionalParams.toString());
|
||||||
|
assertEquals(1, ourLastAdditionalParams.size());
|
||||||
|
assertEquals("val3", ourLastAdditionalParams.get("param3").get(0));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchTwoOptionalParamsWithQualifierAndExtraParam() throws Exception {
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?param1=val1¶m2=val2¶m2:exact=val2e¶m3=val3&_pretty=true");
|
||||||
|
CloseableHttpResponse status = ourClient.execute(httpGet);
|
||||||
|
try {
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
|
ourLog.info(responseContent);
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
|
assertEquals("search03", ourLastMethod);
|
||||||
|
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertThat(ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertEquals("val1", ourLastParam1.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
|
||||||
|
assertThat(ourLastParam2.getValuesAsQueryTokens(), hasSize(2));
|
||||||
|
assertThat(ourLastParam2.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens(), hasSize(1));
|
||||||
|
assertEquals("val2", ourLastParam2.getValuesAsQueryTokens().get(0).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
assertEquals("val2e", ourLastParam2.getValuesAsQueryTokens().get(1).getValuesAsQueryTokens().get(0).getValue());
|
||||||
|
|
||||||
|
ourLog.info(ourLastAdditionalParams.toString());
|
||||||
|
assertEquals(1, ourLastAdditionalParams.size());
|
||||||
|
assertEquals("val3", ourLastAdditionalParams.get("param3").get(0));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(status.getEntity().getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() throws Exception {
|
||||||
|
ourServer.stop();
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception {
|
||||||
|
ourPort = PortUtil.findFreePort();
|
||||||
|
ourServer = new Server(ourPort);
|
||||||
|
|
||||||
|
DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider();
|
||||||
|
|
||||||
|
ServletHandler proxyHandler = new ServletHandler();
|
||||||
|
RestfulServer servlet = new RestfulServer(ourCtx);
|
||||||
|
servlet.setPagingProvider(new FifoMemoryPagingProvider(10));
|
||||||
|
|
||||||
|
servlet.setResourceProviders(patientProvider);
|
||||||
|
ServletHolder servletHolder = new ServletHolder(servlet);
|
||||||
|
proxyHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
ourServer.setHandler(proxyHandler);
|
||||||
|
ourServer.start();
|
||||||
|
|
||||||
|
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
|
||||||
|
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||||
|
builder.setConnectionManager(connectionManager);
|
||||||
|
ourClient = builder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, List<String>> ourLastAdditionalParams;
|
||||||
|
|
||||||
|
public static class DummyPatientResourceProvider implements IResourceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends IBaseResource> getResourceType() {
|
||||||
|
return Patient.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search()
|
||||||
|
public List<Patient> search01(
|
||||||
|
@OptionalParam(name = "param1") StringAndListParam theParam1) {
|
||||||
|
ourLastMethod = "search01";
|
||||||
|
ourLastParam1 = theParam1;
|
||||||
|
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||||
|
retVal.add((Patient) new Patient().addName(new HumanName().setFamily("FAMILY")).setId("1"));
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search()
|
||||||
|
public List<Patient> search02(
|
||||||
|
@OptionalParam(name = "param1") StringAndListParam theParam1,
|
||||||
|
@OptionalParam(name = "param2") StringAndListParam theParam2) {
|
||||||
|
ourLastMethod = "search02";
|
||||||
|
ourLastParam1 = theParam1;
|
||||||
|
ourLastParam2 = theParam2;
|
||||||
|
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||||
|
retVal.add((Patient) new Patient().addName(new HumanName().setFamily("FAMILY")).setId("1"));
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Search(allowUnknownParams = true)
|
||||||
|
public List<Patient> search03(
|
||||||
|
@OptionalParam(name = "param1") StringAndListParam theParam1,
|
||||||
|
@OptionalParam(name = "param2") StringAndListParam theParam2,
|
||||||
|
@RawParam() Map<String, List<String>> theAdditionalParams) {
|
||||||
|
ourLastMethod = "search03";
|
||||||
|
ourLastParam1 = theParam1;
|
||||||
|
ourLastParam2 = theParam2;
|
||||||
|
ourLastAdditionalParams = theAdditionalParams;
|
||||||
|
ArrayList<Patient> retVal = new ArrayList<Patient>();
|
||||||
|
retVal.add((Patient) new Patient().addName(new HumanName().setFamily("FAMILY")).setId("1"));
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
Loading…
x
Reference in New Issue
Block a user