Merge branch 'ja_20190928_rationalize_search_param_extractor' of github.com:jamesagnew/hapi-fhir into ja_20190928_rationalize_search_param_extractor
This commit is contained in:
commit
b13de41e9f
|
@ -1,4 +1,5 @@
|
|||
|
||||
ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl.expansionRefersToUnknownCs=Unknown CodeSystem URI "{0}" referenced from ValueSet
|
||||
|
||||
# Core Library Messages
|
||||
ca.uhn.fhir.context.FhirContext.unknownResourceName=Unknown resource name "{0}" (this name is not known in FHIR version "{1}")
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>classes</classifier>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- HAPI-FHIR uses Logback for logging support. The logback library is included automatically by Maven as a part of the hapi-fhir-base dependency, but you also need to include a logging library. Logback
|
||||
|
|
|
@ -979,7 +979,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao,
|
|||
if (thePerformIndexing) {
|
||||
|
||||
newParams = new ResourceIndexedSearchParams();
|
||||
mySearchParamWithInlineReferencesExtractor.populateFromResource(newParams, this, theUpdateTime, theEntity, theResource, existingParams, theRequest);
|
||||
mySearchParamWithInlineReferencesExtractor.populateFromResource(newParams, theUpdateTime, theEntity, theResource, existingParams, theRequest);
|
||||
|
||||
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, true);
|
||||
if (changed.isChanged()) {
|
||||
|
|
|
@ -132,13 +132,16 @@ public class FhirResourceDaoCodeSystemDstu3 extends BaseHapiFhirResourceDao<Code
|
|||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
|
||||
CodeSystem csDstu3 = (CodeSystem) theResource;
|
||||
CodeSystem csDstu3 = (CodeSystem) theResource;
|
||||
|
||||
org.hl7.fhir.r4.model.CodeSystem cs = VersionConvertor_30_40.convertCodeSystem(csDstu3);
|
||||
addPidToResource(theEntity, cs);
|
||||
org.hl7.fhir.r4.model.CodeSystem cs = VersionConvertor_30_40.convertCodeSystem(csDstu3);
|
||||
addPidToResource(theEntity, cs);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity);
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity);
|
||||
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -161,16 +161,18 @@ public class FhirResourceDaoConceptMapDstu3 extends BaseHapiFhirResourceDao<Conc
|
|||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (retVal.getDeleted() == null) {
|
||||
try {
|
||||
ConceptMap conceptMap = (ConceptMap) theResource;
|
||||
org.hl7.fhir.r4.model.ConceptMap converted = VersionConvertor_30_40.convertConceptMap(conceptMap);
|
||||
myHapiTerminologySvc.storeTermConceptMapAndChildren(retVal, converted);
|
||||
} catch (FHIRException fe) {
|
||||
throw new InternalErrorException(fe);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
try {
|
||||
ConceptMap conceptMap = (ConceptMap) theResource;
|
||||
org.hl7.fhir.r4.model.ConceptMap converted = VersionConvertor_30_40.convertConceptMap(conceptMap);
|
||||
myHapiTerminologySvc.storeTermConceptMapAndChildren(retVal, converted);
|
||||
} catch (FHIRException fe) {
|
||||
throw new InternalErrorException(fe);
|
||||
}
|
||||
} else {
|
||||
myHapiTerminologySvc.deleteConceptMapAndChildren(retVal);
|
||||
}
|
||||
} else {
|
||||
myHapiTerminologySvc.deleteConceptMapAndChildren(retVal);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
|
|
@ -415,7 +415,7 @@ public class FhirResourceDaoValueSetDstu3 extends BaseHapiFhirResourceDao<ValueS
|
|||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (myDaoConfig.isPreExpandValueSets()) {
|
||||
if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
try {
|
||||
ValueSet valueSet = (ValueSet) theResource;
|
||||
|
|
|
@ -88,8 +88,8 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||
protected EntityManager myEntityManager;
|
||||
|
||||
public void populateFromResource(ResourceIndexedSearchParams theParams, IDao theCallingDao, Date theUpdateTime, ResourceTable theEntity, IBaseResource theResource, ResourceIndexedSearchParams theExistingParams, RequestDetails theRequest) {
|
||||
mySearchParamExtractorService.extractFromResource(theParams, theEntity, theResource);
|
||||
public void populateFromResource(ResourceIndexedSearchParams theParams, Date theUpdateTime, ResourceTable theEntity, IBaseResource theResource, ResourceIndexedSearchParams theExistingParams, RequestDetails theRequest) {
|
||||
mySearchParamExtractorService.extractFromResource(theRequest, theParams, theEntity, theResource);
|
||||
|
||||
Set<Map.Entry<String, RuntimeSearchParam>> activeSearchParams = mySearchParamRegistry.getActiveSearchParams(theEntity.getResourceType()).entrySet();
|
||||
if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.ENABLED) {
|
||||
|
|
|
@ -136,10 +136,12 @@ public class FhirResourceDaoCodeSystemR4 extends BaseHapiFhirResourceDao<CodeSys
|
|||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
CodeSystem cs = (CodeSystem) theResource;
|
||||
addPidToResource(theEntity, theResource);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
CodeSystem cs = (CodeSystem) theResource;
|
||||
addPidToResource(theEntity, theResource);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity);
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(cs, theEntity);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -161,11 +161,13 @@ public class FhirResourceDaoConceptMapR4 extends BaseHapiFhirResourceDao<Concept
|
|||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (retVal.getDeleted() == null) {
|
||||
ConceptMap conceptMap = (ConceptMap) theResource;
|
||||
myHapiTerminologySvc.storeTermConceptMapAndChildren(retVal, conceptMap);
|
||||
} else {
|
||||
myHapiTerminologySvc.deleteConceptMapAndChildren(retVal);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
ConceptMap conceptMap = (ConceptMap) theResource;
|
||||
myHapiTerminologySvc.storeTermConceptMapAndChildren(retVal, conceptMap);
|
||||
} else {
|
||||
myHapiTerminologySvc.deleteConceptMapAndChildren(retVal);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
|
|
@ -396,7 +396,7 @@ public class FhirResourceDaoValueSetR4 extends BaseHapiFhirResourceDao<ValueSet>
|
|||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (myDaoConfig.isPreExpandValueSets()) {
|
||||
if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
ValueSet valueSet = (ValueSet) theResource;
|
||||
myHapiTerminologySvc.storeTermValueSet(retVal, valueSet);
|
||||
|
|
|
@ -135,11 +135,13 @@ public class FhirResourceDaoCodeSystemR5 extends BaseHapiFhirResourceDao<CodeSys
|
|||
public ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
|
||||
CodeSystem cs = (CodeSystem) theResource;
|
||||
addPidToResource(theEntity, theResource);
|
||||
CodeSystem cs = (CodeSystem) theResource;
|
||||
addPidToResource(theEntity, theResource);
|
||||
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem(cs), theEntity);
|
||||
myTerminologyCodeSystemStorageSvc.storeNewCodeSystemVersionIfNeeded(org.hl7.fhir.convertors.conv40_50.CodeSystem.convertCodeSystem(cs), theEntity);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -161,14 +161,16 @@ public class FhirResourceDaoConceptMapR5 extends BaseHapiFhirResourceDao<Concept
|
|||
public ResourceTable updateEntity(RequestDetails theRequestDetails, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
if (!retVal.isUnchangedInCurrentOperation()) {
|
||||
|
||||
if (retVal.getDeleted() == null) {
|
||||
ConceptMap conceptMap = (ConceptMap) theResource;
|
||||
myHapiTerminologySvc.storeTermConceptMapAndChildren(retVal, org.hl7.fhir.convertors.conv40_50.ConceptMap.convertConceptMap(conceptMap));
|
||||
} else {
|
||||
myHapiTerminologySvc.deleteConceptMapAndChildren(retVal);
|
||||
if (retVal.getDeleted() == null) {
|
||||
ConceptMap conceptMap = (ConceptMap) theResource;
|
||||
myHapiTerminologySvc.storeTermConceptMapAndChildren(retVal, org.hl7.fhir.convertors.conv40_50.ConceptMap.convertConceptMap(conceptMap));
|
||||
} else {
|
||||
myHapiTerminologySvc.deleteConceptMapAndChildren(retVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ public class FhirResourceDaoValueSetR5 extends BaseHapiFhirResourceDao<ValueSet>
|
|||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||
ResourceTable retVal = super.updateEntity(theRequestDetails, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||
|
||||
if (myDaoConfig.isPreExpandValueSets()) {
|
||||
if (myDaoConfig.isPreExpandValueSets() && !retVal.isUnchangedInCurrentOperation()) {
|
||||
if (retVal.getDeleted() == null) {
|
||||
ValueSet valueSet = (ValueSet) theResource;
|
||||
myHapiTerminologySvc.storeTermValueSet(retVal, org.hl7.fhir.convertors.conv40_50.ValueSet.convertValueSet(valueSet));
|
||||
|
|
|
@ -19,24 +19,25 @@ package ca.uhn.fhir.jpa.provider.r4;
|
|||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.CapabilityStatement.*;
|
||||
import org.hl7.fhir.r4.model.Enumerations.SearchParamType;
|
||||
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.CapabilityStatement.*;
|
||||
import org.hl7.fhir.r4.model.Enumerations.SearchParamType;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
@ -50,17 +51,17 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
private boolean myIncludeResourceCounts;
|
||||
private RestfulServer myRestfulServer;
|
||||
private IFhirSystemDao<Bundle, Meta> mySystemDao;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@CoverageIgnore
|
||||
public JpaConformanceProviderR4(){
|
||||
public JpaConformanceProviderR4() {
|
||||
super();
|
||||
super.setCache(false);
|
||||
setIncludeResourceCounts(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -94,7 +95,7 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
for (CapabilityStatementRestResourceComponent nextResource : nextRest.getResource()) {
|
||||
|
||||
nextResource.setVersioning(ResourceVersionPolicy.VERSIONEDUPDATE);
|
||||
|
||||
|
||||
ConditionalDeleteStatus conditionalDelete = nextResource.getConditionalDelete();
|
||||
if (conditionalDelete == ConditionalDeleteStatus.MULTIPLE && myDaoConfig.isAllowMultipleDelete() == false) {
|
||||
nextResource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
|
@ -109,7 +110,7 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
nextResource.getSearchParam().clear();
|
||||
String resourceName = nextResource.getType();
|
||||
RuntimeResourceDefinition resourceDef = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
for (RuntimeSearchParam runtimeSp : searchParams) {
|
||||
CapabilityStatementRestResourceSearchParamComponent confSp = nextResource.addSearchParam();
|
||||
|
||||
|
@ -117,37 +118,40 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
confSp.setDocumentation(runtimeSp.getDescription());
|
||||
confSp.setDefinition(runtimeSp.getUri());
|
||||
switch (runtimeSp.getParamType()) {
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case SPECIAL:
|
||||
confSp.setType(SearchParamType.SPECIAL);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +165,7 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
}
|
||||
|
||||
massage(retVal);
|
||||
|
||||
|
||||
retVal.getImplementation().setDescription(myImplementationDescription);
|
||||
myCachedValue = retVal;
|
||||
return retVal;
|
||||
|
@ -170,7 +174,11 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
public boolean isIncludeResourceCounts() {
|
||||
return myIncludeResourceCounts;
|
||||
}
|
||||
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
|
@ -187,10 +195,6 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||
myImplementationDescription = theImplDesc;
|
||||
}
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRestfulServer(RestfulServer theRestfulServer) {
|
||||
this.myRestfulServer = theRestfulServer;
|
||||
|
|
|
@ -51,16 +51,16 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
private boolean myIncludeResourceCounts;
|
||||
private RestfulServer myRestfulServer;
|
||||
private IFhirSystemDao<Bundle, Meta> mySystemDao;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@CoverageIgnore
|
||||
public JpaConformanceProviderR5(){
|
||||
public JpaConformanceProviderR5() {
|
||||
super();
|
||||
setIncludeResourceCounts(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -93,7 +93,7 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
for (CapabilityStatementRestResourceComponent nextResource : nextRest.getResource()) {
|
||||
|
||||
nextResource.setVersioning(ResourceVersionPolicy.VERSIONEDUPDATE);
|
||||
|
||||
|
||||
ConditionalDeleteStatus conditionalDelete = nextResource.getConditionalDelete();
|
||||
if (conditionalDelete == ConditionalDeleteStatus.MULTIPLE && myDaoConfig.isAllowMultipleDelete() == false) {
|
||||
nextResource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
|
@ -108,7 +108,7 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
nextResource.getSearchParam().clear();
|
||||
String resourceName = nextResource.getType();
|
||||
RuntimeResourceDefinition resourceDef = myRestfulServer.getFhirContext().getResourceDefinition(resourceName);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
Collection<RuntimeSearchParam> searchParams = mySearchParamRegistry.getSearchParamsByResourceType(resourceDef);
|
||||
for (RuntimeSearchParam runtimeSp : searchParams) {
|
||||
CapabilityStatementRestResourceSearchParamComponent confSp = nextResource.addSearchParam();
|
||||
|
||||
|
@ -116,37 +116,40 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
confSp.setDocumentation(runtimeSp.getDescription());
|
||||
confSp.setDefinition(runtimeSp.getUri());
|
||||
switch (runtimeSp.getParamType()) {
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
case COMPOSITE:
|
||||
confSp.setType(SearchParamType.COMPOSITE);
|
||||
break;
|
||||
case DATE:
|
||||
confSp.setType(SearchParamType.DATE);
|
||||
break;
|
||||
case NUMBER:
|
||||
confSp.setType(SearchParamType.NUMBER);
|
||||
break;
|
||||
case QUANTITY:
|
||||
confSp.setType(SearchParamType.QUANTITY);
|
||||
break;
|
||||
case REFERENCE:
|
||||
confSp.setType(SearchParamType.REFERENCE);
|
||||
break;
|
||||
case STRING:
|
||||
confSp.setType(SearchParamType.STRING);
|
||||
break;
|
||||
case TOKEN:
|
||||
confSp.setType(SearchParamType.TOKEN);
|
||||
break;
|
||||
case URI:
|
||||
confSp.setType(SearchParamType.URI);
|
||||
break;
|
||||
case SPECIAL:
|
||||
confSp.setType(SearchParamType.SPECIAL);
|
||||
break;
|
||||
case HAS:
|
||||
// Shouldn't happen
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +163,7 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
}
|
||||
|
||||
massage(retVal);
|
||||
|
||||
|
||||
retVal.getImplementation().setDescription(myImplementationDescription);
|
||||
myCachedValue = retVal;
|
||||
return retVal;
|
||||
|
@ -169,7 +172,11 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
public boolean isIncludeResourceCounts() {
|
||||
return myIncludeResourceCounts;
|
||||
}
|
||||
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override
|
||||
*/
|
||||
|
@ -186,10 +193,6 @@ public class JpaConformanceProviderR5 extends org.hl7.fhir.r5.hapi.rest.server.S
|
|||
myImplementationDescription = theImplDesc;
|
||||
}
|
||||
|
||||
public void setIncludeResourceCounts(boolean theIncludeResourceCounts) {
|
||||
myIncludeResourceCounts = theIncludeResourceCounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRestfulServer(RestfulServer theRestfulServer) {
|
||||
this.myRestfulServer = theRestfulServer;
|
||||
|
|
|
@ -195,6 +195,11 @@ public class ResourceReindexingSvcImpl implements IResourceReindexingSvc {
|
|||
mySchedulerService.scheduleFixedDelay(10 * DateUtils.MILLIS_PER_SECOND, true, jobDetail);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ReentrantLock getIndexingLockForUnitTest() {
|
||||
return myIndexingLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(Transactional.TxType.NEVER)
|
||||
public Integer runReindexingPass() {
|
||||
|
|
|
@ -675,7 +675,10 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc, ApplicationCo
|
|||
|
||||
CodeSystem codeSystemFromContext = getCodeSystemFromContext(system);
|
||||
if (codeSystemFromContext == null) {
|
||||
throw new InvalidRequestException("Unknown code system: " + system);
|
||||
String msg = myContext.getLocalizer().getMessage(BaseTermReadSvcImpl.class, "expansionRefersToUnknownCs", system);
|
||||
ourLog.warn(msg);
|
||||
theValueSetCodeAccumulator.addMessage(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!theIncludeOrExclude.getConcept().isEmpty()) {
|
||||
|
|
|
@ -27,6 +27,8 @@ import java.util.Collection;
|
|||
|
||||
public interface IValueSetConceptAccumulator {
|
||||
|
||||
void addMessage(String theMessage);
|
||||
|
||||
void includeConcept(String theSystem, String theCode, String theDisplay);
|
||||
|
||||
void includeConceptWithDesignations(String theSystem, String theCode, String theDisplay, Collection<TermConceptDesignation> theDesignations);
|
||||
|
|
|
@ -57,6 +57,12 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
myConceptsExcluded = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessage(String theMessage) {
|
||||
// ignore for now
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void includeConcept(String theSystem, String theCode, String theDisplay) {
|
||||
saveConcept(theSystem, theCode, theDisplay);
|
||||
|
@ -82,7 +88,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
if (optionalConcept.isPresent()) {
|
||||
TermValueSetConcept concept = optionalConcept.get();
|
||||
|
||||
ourLog.info("Excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
ourLog.debug("Excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
for (TermValueSetConceptDesignation designation : concept.getDesignations()) {
|
||||
myValueSetConceptDesignationDao.deleteById(designation.getId());
|
||||
myTermValueSet.decrementTotalConceptDesignations();
|
||||
|
@ -90,7 +96,7 @@ public class ValueSetConceptAccumulator implements IValueSetConceptAccumulator {
|
|||
myValueSetConceptDao.deleteById(concept.getId());
|
||||
myTermValueSet.decrementTotalConcepts();
|
||||
myValueSetDao.save(myTermValueSet);
|
||||
ourLog.info("Done excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
ourLog.debug("Done excluding [{}|{}] from ValueSet[{}]", concept.getSystem(), concept.getCode(), myTermValueSet.getUrl());
|
||||
|
||||
if (++myConceptsExcluded % 250 == 0) {
|
||||
ourLog.info("Have excluded {} concepts from ValueSet[{}]", myConceptsExcluded, myTermValueSet.getUrl());
|
||||
|
|
|
@ -22,9 +22,11 @@ package ca.uhn.fhir.jpa.term;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.term.ex.ExpansionTooCostlyException;
|
||||
import ca.uhn.fhir.model.api.annotation.Block;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -54,6 +56,13 @@ public class ValueSetExpansionComponentWithConceptAccumulator extends ValueSet.V
|
|||
return myMaxCapacity - myConceptsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessage(String theMessage) {
|
||||
addExtension()
|
||||
.setUrl(JpaConstants.EXT_VALUESET_EXPANSION_MESSAGE)
|
||||
.setValue(new StringType(theMessage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void includeConcept(String theSystem, String theCode, String theDisplay) {
|
||||
incrementConceptsCount();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.dao.r5;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.util.TestUtil;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
|
@ -9,11 +11,14 @@ import ca.uhn.fhir.rest.param.HasOrListParam;
|
|||
import ca.uhn.fhir.rest.param.HasParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import org.hl7.fhir.r5.model.Organization;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
import org.hl7.fhir.r5.model.Practitioner;
|
||||
import org.hl7.fhir.r5.model.PractitionerRole;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@SuppressWarnings({"unchecked", "Duplicates"})
|
||||
|
@ -98,6 +103,40 @@ public class FhirResourceDaoR5SearchNoFtTest extends BaseJpaR5Test {
|
|||
assertEquals(1, outcome.getResources(0, 1).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchDoesntFailIfResourcesAreDeleted() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.addIdentifier().setValue("1");
|
||||
myPatientDao.create(p);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setValue("2");
|
||||
myPatientDao.create(p);
|
||||
|
||||
p = new Patient();
|
||||
p.addIdentifier().setValue("3");
|
||||
Long id = myPatientDao.create(p).getId().getIdPartAsLong();
|
||||
|
||||
IBundleProvider outcome = myPatientDao.search(new SearchParameterMap());
|
||||
assertEquals(3, outcome.size().intValue());
|
||||
|
||||
runInTransaction(()->{
|
||||
ResourceTable table = myResourceTableDao.findById(id).orElseThrow(() -> new IllegalArgumentException());
|
||||
table.setDeleted(new Date());
|
||||
myResourceTableDao.save(table);
|
||||
});
|
||||
|
||||
assertEquals(2, outcome.getResources(0, 3).size());
|
||||
|
||||
runInTransaction(()->{
|
||||
myResourceHistoryTableDao.deleteAll();
|
||||
});
|
||||
|
||||
assertEquals(0, outcome.getResources(0, 3).size());
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -4080,22 +4080,16 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
Patient patient = new Patient();
|
||||
patient.addName().addGiven("James");
|
||||
patient.setBirthDateElement(new DateType("2011-02-02"));
|
||||
patient.addContact().setGender(AdministrativeGender.MALE);
|
||||
|
||||
String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(patient);
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
|
||||
post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||
|
||||
CloseableHttpResponse response = ourHttpClient.execute(post);
|
||||
try {
|
||||
try (CloseableHttpResponse response = ourHttpClient.execute(post)) {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(resp);
|
||||
assertEquals(412, response.getStatusLine().getStatusCode());
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
assertThat(resp, not(containsString("Resource has no id")));
|
||||
assertThat(resp, containsString("<issue><severity value=\"error\"/><code value=\"processing\"/><diagnostics value=\"SHALL at least contain a contact's details or a reference to an organization [name.exists() or telecom.exists() or address.exists() or organization.exists()]\"/><location value=\"Patient.contact[0]\"/><location value=\"Line 0, Col 0\"/></issue>"));
|
||||
} finally {
|
||||
IOUtils.closeQuietly(response.getEntity().getContent());
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||
private static SubscriptionMatcherInterceptor ourSubscriptionMatcherInterceptor;
|
||||
protected static Server ourServer;
|
||||
protected IGenericClient ourClient;
|
||||
ResourceCountCache ourResourceCountsCache;
|
||||
ResourceCountCache myResourceCountsCache;
|
||||
private TerminologyUploaderProvider myTerminologyUploaderProvider;
|
||||
private boolean ourRestHookSubscriptionInterceptorRequested;
|
||||
|
||||
|
@ -93,6 +93,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||
myFhirCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
|
||||
myFhirCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
|
||||
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
|
||||
myResourceCountsCache = (ResourceCountCache) myAppCtx.getBean("myResourceCountsCache");
|
||||
|
||||
if (ourServer == null) {
|
||||
ourRestServer = new RestfulServer(myFhirCtx);
|
||||
|
@ -113,7 +114,6 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||
ourRestServer.setServerConformanceProvider(confProvider);
|
||||
|
||||
ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class);
|
||||
ourResourceCountsCache = (ResourceCountCache) myAppCtx.getBean("myResourceCountsCache");
|
||||
|
||||
Server server = new Server(0);
|
||||
|
||||
|
|
|
@ -5308,7 +5308,6 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
Patient patient = new Patient();
|
||||
patient.addName().addGiven("James");
|
||||
patient.setBirthDateElement(new DateType("2011-02-02"));
|
||||
patient.addContact().setGender(AdministrativeGender.MALE);
|
||||
|
||||
String inputStr = myFhirCtx.newXmlParser().encodeResourceToString(patient);
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
|
||||
|
@ -5317,9 +5316,8 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
try (CloseableHttpResponse response = ourHttpClient.execute(post)) {
|
||||
String resp = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(resp);
|
||||
assertEquals(412, response.getStatusLine().getStatusCode());
|
||||
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||
assertThat(resp, not(containsString("Resource has no id")));
|
||||
assertThat(resp, containsString("<issue><severity value=\"error\"/><code value=\"processing\"/><diagnostics value=\"SHALL at least contain a contact's details or a reference to an organization [name.exists() or telecom.exists() or address.exists() or organization.exists()]\"/><location value=\"Patient.contact[0]\"/><location value=\"Line 0, Col 0\"/></issue>"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package ca.uhn.fhir.jpa.provider.r4;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -13,6 +16,7 @@ import org.hl7.fhir.r4.model.Extension;
|
|||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -25,6 +29,29 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerR4Test.class);
|
||||
|
||||
@Autowired
|
||||
private IFhirResourceDao<CapabilityStatement> myCapabilityStatementDao;
|
||||
|
||||
@Test
|
||||
public void testCapabilityStatementValidates() throws IOException {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/metadata?_pretty=true&_format=json");
|
||||
try (CloseableHttpResponse resp = ourHttpClient.execute(get)) {
|
||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
|
||||
ourLog.info(respString);
|
||||
|
||||
CapabilityStatement cs = myFhirCtx.newJsonParser().parseResource(CapabilityStatement.class, respString);
|
||||
|
||||
try {
|
||||
myCapabilityStatementDao.validate(cs, null, respString, EncodingEnum.JSON, null, null, null);
|
||||
} catch (PreconditionFailedException e) {
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #519
|
||||
|
@ -71,7 +98,7 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||
* Initial fetch after a clear should return
|
||||
* no results
|
||||
*/
|
||||
ourResourceCountsCache.clear();
|
||||
myResourceCountsCache.clear();
|
||||
|
||||
CapabilityStatement capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
|
@ -93,7 +120,7 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||
* Now run a background pass (the update
|
||||
* method is called by the scheduler normally)
|
||||
*/
|
||||
ourResourceCountsCache.update();
|
||||
myResourceCountsCache.update();
|
||||
|
||||
capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
package ca.uhn.fhir.jpa.provider.r5;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.util.ExtensionConstants;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ServerR5Test extends BaseResourceProviderR5Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerR5Test.class);
|
||||
|
||||
@Autowired
|
||||
private IFhirResourceDao<CapabilityStatement> myCapabilityStatementDao;
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCapabilityStatementValidates() throws IOException {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/metadata?_pretty=true&_format=json");
|
||||
try (CloseableHttpResponse resp = ourHttpClient.execute(get)) {
|
||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
|
||||
ourLog.info(respString);
|
||||
|
||||
CapabilityStatement cs = myFhirCtx.newJsonParser().parseResource(CapabilityStatement.class, respString);
|
||||
|
||||
try {
|
||||
myCapabilityStatementDao.validate(cs, null, respString, EncodingEnum.JSON, null, null, null);
|
||||
} catch (PreconditionFailedException e) {
|
||||
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #519
|
||||
*/
|
||||
@Test
|
||||
public void saveIdParamOnlyAppearsOnce() throws IOException {
|
||||
HttpGet get = new HttpGet(ourServerBase + "/metadata?_pretty=true&_format=xml");
|
||||
CloseableHttpResponse resp = ourHttpClient.execute(get);
|
||||
try {
|
||||
ourLog.info(resp.toString());
|
||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
|
||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||
ourLog.info(respString);
|
||||
|
||||
CapabilityStatement cs = myFhirCtx.newXmlParser().parseResource(CapabilityStatement.class, respString);
|
||||
|
||||
for (CapabilityStatementRestResourceComponent nextResource : cs.getRest().get(0).getResource()) {
|
||||
ourLog.info("Testing resource: " + nextResource.getType());
|
||||
Set<String> sps = new HashSet<String>();
|
||||
for (CapabilityStatementRestResourceSearchParamComponent nextSp : nextResource.getSearchParam()) {
|
||||
if (sps.add(nextSp.getName()) == false) {
|
||||
fail("Duplicate search parameter " + nextSp.getName() + " for resource " + nextResource.getType());
|
||||
}
|
||||
}
|
||||
|
||||
if (!sps.contains("_id")) {
|
||||
fail("No search parameter _id for resource " + nextResource.getType());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(resp.getEntity().getContent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMetadataIncludesResourceCounts() {
|
||||
Patient p = new Patient();
|
||||
p.setActive(true);
|
||||
ourClient.create().resource(p).execute();
|
||||
|
||||
/*
|
||||
* Initial fetch after a clear should return
|
||||
* no results
|
||||
*/
|
||||
myResourceCountsCache.clear();
|
||||
|
||||
CapabilityStatement capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
.ofType(CapabilityStatement.class)
|
||||
.execute();
|
||||
|
||||
Extension patientCountExt = capabilityStatement
|
||||
.getRest()
|
||||
.get(0)
|
||||
.getResource()
|
||||
.stream()
|
||||
.filter(t -> t.getType().equals("Patient"))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new InternalErrorException("No patient"))
|
||||
.getExtensionByUrl(ExtensionConstants.CONF_RESOURCE_COUNT);
|
||||
assertNull(patientCountExt);
|
||||
|
||||
/*
|
||||
* Now run a background pass (the update
|
||||
* method is called by the scheduler normally)
|
||||
*/
|
||||
myResourceCountsCache.update();
|
||||
|
||||
capabilityStatement = ourClient
|
||||
.capabilities()
|
||||
.ofType(CapabilityStatement.class)
|
||||
.execute();
|
||||
|
||||
patientCountExt = capabilityStatement
|
||||
.getRest()
|
||||
.get(0)
|
||||
.getResource()
|
||||
.stream()
|
||||
.filter(t -> t.getType().equals("Patient"))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new InternalErrorException("No patient"))
|
||||
.getExtensionByUrl(ExtensionConstants.CONF_RESOURCE_COUNT);
|
||||
assertEquals("1", patientCountExt.getValueAsPrimitive().getValueAsString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,8 @@ import org.springframework.data.domain.SliceImpl;
|
|||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -94,6 +96,17 @@ public class ResourceReindexingSvcImplTest extends BaseJpaTest {
|
|||
mySvc.start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoParallelReindexing() throws InterruptedException {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
new Thread(()->{
|
||||
mySvc.getIndexingLockForUnitTest().lock();
|
||||
latch.countDown();
|
||||
}).start();
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
mySvc.runReindexingPass();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReindexPassOnlyReturnsValuesAtLowThreshold() {
|
||||
mockNothingToExpunge();
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package ca.uhn.fhir.jpa.term;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDesignationDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.ITermValueSetDao;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ValueSetConceptAccumulatorTest {
|
||||
|
||||
private ValueSetConceptAccumulator myAccumulator;
|
||||
private TermValueSet myValueSet;
|
||||
@Mock
|
||||
private ITermValueSetDao myValueSetDao;
|
||||
@Mock
|
||||
private ITermValueSetConceptDesignationDao myValueSetDesignationDao;
|
||||
@Mock
|
||||
private ITermValueSetConceptDao myValueSetConceptDao;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
myValueSet = new TermValueSet();
|
||||
myAccumulator = new ValueSetConceptAccumulator(myValueSet, myValueSetDao, myValueSetConceptDao, myValueSetDesignationDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncludeConcept() {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
myAccumulator.includeConcept("sys", "code", "display");
|
||||
}
|
||||
verify(myValueSetConceptDao, times(1000)).save(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludeBlankConcept() {
|
||||
myAccumulator.excludeConcept("", "");
|
||||
verifyNoInteractions(myValueSetConceptDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddMessage() {
|
||||
myAccumulator.addMessage("foo");
|
||||
verifyNoInteractions(myValueSetConceptDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExcludeConceptWithDesignations() {
|
||||
for (int i = 0; i <1000; i++) {
|
||||
|
||||
TermValueSetConcept value = new TermValueSetConcept();
|
||||
value.setCode("code");
|
||||
value.getDesignations().add(new TermValueSetConceptDesignation().setValue("foo"));
|
||||
|
||||
when(myValueSetConceptDao.findByTermValueSetIdSystemAndCode(any(), eq("sys"), eq("code"+i))).thenReturn(Optional.of(value));
|
||||
|
||||
myAccumulator.excludeConcept("sys", "code"+i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,13 @@ package ca.uhn.fhir.jpa.term;
|
|||
|
||||
import ca.uhn.fhir.jpa.entity.*;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.Extension;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.r4.model.codesystems.HttpVerb;
|
||||
import org.junit.Test;
|
||||
|
@ -688,6 +690,21 @@ public class ValueSetExpansionR4Test extends BaseTermR4Test {
|
|||
assertEquals("Systolische bloeddruk minimaal 1 uur", designationComponent.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandValueSetWithUnknownCodeSystem() {
|
||||
ValueSet vs = new ValueSet();
|
||||
ValueSet.ConceptSetComponent include = vs.getCompose().addInclude();
|
||||
include.setSystem("http://unknown-system");
|
||||
ValueSet outcome = myTermSvc.expandValueSetInMemory(vs, null);
|
||||
assertEquals(0, outcome.getExpansion().getContains().size());
|
||||
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome);
|
||||
ourLog.info(encoded);
|
||||
|
||||
Extension extensionByUrl = outcome.getExpansion().getExtensionByUrl(JpaConstants.EXT_VALUESET_EXPANSION_MESSAGE);
|
||||
assertEquals("Unknown CodeSystem URI \"http://unknown-system\" referenced from ValueSet", extensionByUrl.getValueAsPrimitive().getValueAsString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExpandTermValueSetAndChildrenWithOffsetAndCountWithClientAssignedId() throws Exception {
|
||||
myDaoConfig.setPreExpandValueSets(true);
|
||||
|
|
|
@ -24,6 +24,13 @@ import ca.uhn.fhir.rest.api.Constants;
|
|||
|
||||
public class JpaConstants {
|
||||
|
||||
/**
|
||||
* Non-instantiable
|
||||
*/
|
||||
private JpaConstants() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation name for the $apply-codesystem-delta-add operation
|
||||
*/
|
||||
|
@ -243,6 +250,12 @@ public class JpaConstants {
|
|||
*/
|
||||
public static final String EXTENSION_EXT_SYSTEMDEFINED = JpaConstants.class.getName() + "_EXTENSION_EXT_SYSTEMDEFINED";
|
||||
|
||||
/**
|
||||
* Message added to expansion valueset
|
||||
*/
|
||||
public static final String EXT_VALUESET_EXPANSION_MESSAGE = "http://hapifhir.io/fhir/StructureDefinition/valueset-expansion-message";
|
||||
|
||||
|
||||
/**
|
||||
* Parameter for the $export operation
|
||||
*/
|
||||
|
|
|
@ -122,6 +122,11 @@
|
|||
<artifactId>spring-boot-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
|
|
@ -59,6 +59,43 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
@Autowired
|
||||
private ModelConfig myModelConfig;
|
||||
private Set<String> myIgnoredForSearchDatatypes;
|
||||
private BaseRuntimeChildDefinition myQuantityValueValueChild;
|
||||
private BaseRuntimeChildDefinition myQuantitySystemValueChild;
|
||||
private BaseRuntimeChildDefinition myQuantityCodeValueChild;
|
||||
private BaseRuntimeChildDefinition myMoneyValueChild;
|
||||
private BaseRuntimeChildDefinition myMoneyCurrencyChild;
|
||||
private BaseRuntimeElementCompositeDefinition<?> myLocationPositionDefinition;
|
||||
private BaseRuntimeChildDefinition myCodeSystemUrlValueChild;
|
||||
private BaseRuntimeChildDefinition myRangeLowValueChild;
|
||||
private BaseRuntimeChildDefinition myRangeHighValueChild;
|
||||
private BaseRuntimeChildDefinition myAddressLineValueChild;
|
||||
private BaseRuntimeChildDefinition myAddressCityValueChild;
|
||||
private BaseRuntimeChildDefinition myAddressStateValueChild;
|
||||
private BaseRuntimeChildDefinition myAddressCountryValueChild;
|
||||
private BaseRuntimeChildDefinition myAddressPostalCodeValueChild;
|
||||
private BaseRuntimeChildDefinition myCapabilityStatementRestSecurityServiceValueChild;
|
||||
private BaseRuntimeChildDefinition myPeriodStartValueChild;
|
||||
private BaseRuntimeChildDefinition myPeriodEndValueChild;
|
||||
private BaseRuntimeChildDefinition myTimingEventValueChild;
|
||||
private BaseRuntimeChildDefinition myTimingRepeatValueChild;
|
||||
private BaseRuntimeChildDefinition myTimingRepeatBoundsValueChild;
|
||||
private BaseRuntimeChildDefinition myDurationSystemValueChild;
|
||||
private BaseRuntimeChildDefinition myDurationCodeValueChild;
|
||||
private BaseRuntimeChildDefinition myDurationValueValueChild;
|
||||
private BaseRuntimeChildDefinition myHumanNameFamilyValueChild;
|
||||
private BaseRuntimeChildDefinition myHumanNameGivenValueChild;
|
||||
private BaseRuntimeChildDefinition myContactPointValueValueChild;
|
||||
private BaseRuntimeChildDefinition myIdentifierSystemValueChild;
|
||||
private BaseRuntimeChildDefinition myIdentifierValueValueChild;
|
||||
private BaseRuntimeChildDefinition myIdentifierTypeValueChild;
|
||||
private BaseRuntimeChildDefinition myIdentifierTypeTextValueChild;
|
||||
private BaseRuntimeChildDefinition myCodeableConceptCodingValueChild;
|
||||
private BaseRuntimeChildDefinition myCodeableConceptTextValueChild;
|
||||
private BaseRuntimeChildDefinition myCodingSystemValueChild;
|
||||
private BaseRuntimeChildDefinition myCodingCodeValueChild;
|
||||
private BaseRuntimeChildDefinition myCodingDisplayValueChild;
|
||||
private BaseRuntimeChildDefinition myContactPointSystemValueChild;
|
||||
private BaseRuntimeChildDefinition myPatientCommunicationLanguageValueChild;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -77,27 +114,20 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource) {
|
||||
BaseRuntimeElementCompositeDefinition<?> codeSystemDefinition;
|
||||
BaseRuntimeChildDefinition codeSystemUrlValueChild = null;
|
||||
if (getContext().getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
codeSystemDefinition = getContext().getResourceDefinition("CodeSystem");
|
||||
assert codeSystemDefinition != null;
|
||||
codeSystemUrlValueChild = codeSystemDefinition.getChildByName("url");
|
||||
}
|
||||
public SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource) {
|
||||
|
||||
String resourceTypeName = toRootTypeName(theResource);
|
||||
String useSystem;
|
||||
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU2)) {
|
||||
if (resourceTypeName.equals("ValueSet")) {
|
||||
ca.uhn.fhir.model.dstu2.resource.ValueSet dstu2ValueSet = (ca.uhn.fhir.model.dstu2.resource.ValueSet)theResource;
|
||||
ca.uhn.fhir.model.dstu2.resource.ValueSet dstu2ValueSet = (ca.uhn.fhir.model.dstu2.resource.ValueSet) theResource;
|
||||
useSystem = dstu2ValueSet.getCodeSystem().getSystem();
|
||||
} else {
|
||||
useSystem = null;
|
||||
}
|
||||
} else {
|
||||
if (resourceTypeName.equals("CodeSystem")) {
|
||||
useSystem = extractValueAsString(codeSystemUrlValueChild, theResource);
|
||||
useSystem = extractValueAsString(myCodeSystemUrlValueChild, theResource);
|
||||
} else {
|
||||
useSystem = null;
|
||||
}
|
||||
|
@ -176,15 +206,20 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
addToken_ContactPoint(resourceTypeName, params, searchParam, value);
|
||||
break;
|
||||
default:
|
||||
throw new ConfigurationException("Search param " + searchParam.getName() + " is of unexpected datatype: " + value.getClass());
|
||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return extractSearchParams(theResource, extractor, RestSearchParameterTypeEnum.TOKEN);
|
||||
}
|
||||
|
||||
private void addUnexpectedDatatypeWarning(SearchParamSet<? extends BaseResourceIndexedSearchParam> params, RuntimeSearchParam searchParam, IBase value) {
|
||||
params.addWarning("Search param " + searchParam.getName() + " is of unexpected datatype: " + value.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource) {
|
||||
public SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource) {
|
||||
IExtractor<ResourceIndexedSearchParamUri> extractor = (params, searchParam, value, path) -> {
|
||||
String nextType = toRootTypeName(value);
|
||||
String resourceType = toRootTypeName(theResource);
|
||||
|
@ -197,7 +232,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
addUri_Uri(resourceType, params, searchParam, value);
|
||||
break;
|
||||
default:
|
||||
throw new ConfigurationException("Search param " + searchParam.getName() + " is of unexpected datatype: " + value.getClass());
|
||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -205,13 +241,12 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceIndexedSearchParamCoords> extractSearchParamCoords(IBaseResource theResource) {
|
||||
// TODO: implement
|
||||
return Collections.emptySet();
|
||||
public SearchParamSet<ResourceIndexedSearchParamCoords> extractSearchParamCoords(IBaseResource theResource) {
|
||||
return new SearchParamSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceIndexedSearchParamDate> extractSearchParamDates(IBaseResource theResource) {
|
||||
public SearchParamSet<ResourceIndexedSearchParamDate> extractSearchParamDates(IBaseResource theResource) {
|
||||
IExtractor<ResourceIndexedSearchParamDate> extractor = (params, searchParam, value, path) -> {
|
||||
String nextType = toRootTypeName(value);
|
||||
String resourceType = toRootTypeName(theResource);
|
||||
|
@ -231,7 +266,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
// CarePlan.activitydate can be a string - ignored for now
|
||||
break;
|
||||
default:
|
||||
throw new ConfigurationException("Search param " + searchParam.getName() + " is of unexpected datatype: " + value.getClass());
|
||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -239,7 +275,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceIndexedSearchParamNumber> extractSearchParamNumber(IBaseResource theResource) {
|
||||
public SearchParamSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(IBaseResource theResource) {
|
||||
|
||||
IExtractor<ResourceIndexedSearchParamNumber> extractor = (params, searchParam, value, path) -> {
|
||||
String nextType = toRootTypeName(value);
|
||||
|
@ -260,7 +296,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
addNumber_Decimal(resourceType, params, searchParam, value);
|
||||
break;
|
||||
default:
|
||||
throw new ConfigurationException("Search param " + searchParam.getName() + " is of unexpected datatype: " + value.getClass());
|
||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -268,14 +305,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource) {
|
||||
BaseRuntimeElementCompositeDefinition<?> locationDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getResourceDefinition("Location");
|
||||
BaseRuntimeChildDefinition locationPositionValueChild = locationDefinition.getChildByName("position");
|
||||
BaseRuntimeElementCompositeDefinition<?> locationPositionDefinition = (BaseRuntimeElementCompositeDefinition<?>) locationPositionValueChild.getChildByName("position");
|
||||
|
||||
public SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource) {
|
||||
|
||||
IExtractor<ResourceIndexedSearchParamQuantity> extractor = (params, searchParam, value, path) -> {
|
||||
if (value.getClass().equals(locationPositionDefinition.getImplementingClass())) {
|
||||
if (value.getClass().equals(myLocationPositionDefinition.getImplementingClass())) {
|
||||
ourLog.warn("Position search not currently supported, not indexing location");
|
||||
return;
|
||||
}
|
||||
|
@ -293,7 +326,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
addQuantity_Range(resourceType, params, searchParam, value);
|
||||
break;
|
||||
default:
|
||||
throw new ConfigurationException("Search param " + searchParam.getName() + " is of unexpected datatype: " + value.getClass());
|
||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -301,7 +335,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource) {
|
||||
public SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource) {
|
||||
IExtractor<ResourceIndexedSearchParamString> extractor = (params, searchParam, value, path) -> {
|
||||
String resourceType = toRootTypeName(theResource);
|
||||
|
||||
|
@ -330,7 +364,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
addString_Range(resourceType, params, searchParam, value);
|
||||
break;
|
||||
default:
|
||||
throw new ConfigurationException("Search param " + searchParam.getName() + " is of unexpected datatype: " + value.getClass());
|
||||
addUnexpectedDatatypeWarning(params, searchParam, value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -356,7 +391,6 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
/**
|
||||
* [
|
||||
* Override parent because we're using FHIRPath here
|
||||
*/
|
||||
private List<IBase> extractValues(String thePaths, IBaseResource theResource) {
|
||||
|
@ -401,7 +435,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
return myModelConfig;
|
||||
}
|
||||
|
||||
public Collection<RuntimeSearchParam> getSearchParams(IBaseResource theResource) {
|
||||
private Collection<RuntimeSearchParam> getSearchParams(IBaseResource theResource) {
|
||||
RuntimeResourceDefinition def = getContext().getResourceDefinition(theResource);
|
||||
Collection<RuntimeSearchParam> retVal = mySearchParamRegistry.getActiveSearchParams(def.getName()).values();
|
||||
List<RuntimeSearchParam> defaultList = Collections.emptyList();
|
||||
|
@ -409,29 +443,14 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myIgnoredForSearchDatatypes = new HashSet<>();
|
||||
addIgnoredType(getContext(), "Annotation", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Attachment", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Count", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Distance", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Ratio", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "SampledData", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Signature", myIgnoredForSearchDatatypes);
|
||||
}
|
||||
|
||||
private void addQuantity_Quantity(String theResourceType, Set<ResourceIndexedSearchParamQuantity> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> quantityDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Quantity");
|
||||
BaseRuntimeChildDefinition quantityValueChild = quantityDefinition.getChildByName("value");
|
||||
BaseRuntimeChildDefinition quantitySystemChild = quantityDefinition.getChildByName("system");
|
||||
BaseRuntimeChildDefinition quantityCodeChild = quantityDefinition.getChildByName("code");
|
||||
|
||||
Optional<IPrimitiveType<BigDecimal>> valueField = quantityValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
Optional<IPrimitiveType<BigDecimal>> valueField = myQuantityValueValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
||||
BigDecimal nextValueValue = valueField.get().getValue();
|
||||
String system = extractValueAsString(quantitySystemChild, theValue);
|
||||
String code = extractValueAsString(quantityCodeChild, theValue);
|
||||
String system = extractValueAsString(myQuantitySystemValueChild, theValue);
|
||||
String code = extractValueAsString(myQuantityCodeValueChild, theValue);
|
||||
|
||||
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(theResourceType, theSearchParam.getName(), nextValueValue, system, code);
|
||||
theParams.add(nextEntity);
|
||||
|
@ -440,16 +459,13 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addQuantity_Money(String theResourceType, Set<ResourceIndexedSearchParamQuantity> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> moneyDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Money");
|
||||
BaseRuntimeChildDefinition moneyValueChild = moneyDefinition.getChildByName("value");
|
||||
BaseRuntimeChildDefinition moneyCurrencyChild = moneyDefinition.getChildByName("currency");
|
||||
|
||||
Optional<IPrimitiveType<BigDecimal>> valueField = moneyValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
Optional<IPrimitiveType<BigDecimal>> valueField = myMoneyValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
if (valueField.isPresent() && valueField.get().getValue() != null) {
|
||||
BigDecimal nextValueValue = valueField.get().getValue();
|
||||
|
||||
String nextValueString = "urn:iso:std:iso:4217";
|
||||
String nextValueCode = extractValueAsString(moneyCurrencyChild, theValue);
|
||||
String nextValueCode = extractValueAsString(myMoneyCurrencyChild, theValue);
|
||||
String searchParamName = theSearchParam.getName();
|
||||
ResourceIndexedSearchParamQuantity nextEntity = new ResourceIndexedSearchParamQuantity(theResourceType, searchParamName, nextValueValue, nextValueString, nextValueCode);
|
||||
theParams.add(nextEntity);
|
||||
|
@ -458,102 +474,65 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addQuantity_Range(String theResourceType, Set<ResourceIndexedSearchParamQuantity> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> rangeDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Range");
|
||||
BaseRuntimeChildDefinition rangeLowValueChild = rangeDefinition.getChildByName("low");
|
||||
BaseRuntimeChildDefinition rangeHighValueChild = rangeDefinition.getChildByName("high");
|
||||
|
||||
Optional<IBase> low = rangeLowValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
Optional<IBase> low = myRangeLowValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
low.ifPresent(theIBase -> addQuantity_Quantity(theResourceType, theParams, theSearchParam, theIBase));
|
||||
|
||||
Optional<IBase> high = rangeHighValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
Optional<IBase> high = myRangeHighValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
high.ifPresent(theIBase -> addQuantity_Quantity(theResourceType, theParams, theSearchParam, theIBase));
|
||||
}
|
||||
|
||||
private void addToken_Identifier(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> identifierDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Identifier");
|
||||
BaseRuntimeChildDefinition identifierSystemValueChild = identifierDefinition.getChildByName("system");
|
||||
BaseRuntimeChildDefinition identifierValueValueChild = identifierDefinition.getChildByName("value");
|
||||
|
||||
BaseRuntimeChildDefinition identifierTypeValueChild = identifierDefinition.getChildByName("type");
|
||||
BaseRuntimeElementCompositeDefinition<?> identifierTypeDefinition = (BaseRuntimeElementCompositeDefinition<?>) identifierTypeValueChild.getChildByName("type");
|
||||
|
||||
BaseRuntimeChildDefinition identifierTypeTextValueChild = identifierTypeDefinition.getChildByName("text");
|
||||
|
||||
String system = extractValueAsString(identifierSystemValueChild, theValue);
|
||||
String value = extractValueAsString(identifierValueValueChild, theValue);
|
||||
String system = extractValueAsString(myIdentifierSystemValueChild, theValue);
|
||||
String value = extractValueAsString(myIdentifierValueValueChild, theValue);
|
||||
if (isNotBlank(value)) {
|
||||
createTokenIndexIfNotBlank(theResourceType, theParams, theSearchParam, system, value);
|
||||
}
|
||||
|
||||
Optional<IBase> type = identifierTypeValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
Optional<IBase> type = myIdentifierTypeValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
if (type.isPresent()) {
|
||||
String text = extractValueAsString(identifierTypeTextValueChild, type.get());
|
||||
String text = extractValueAsString(myIdentifierTypeTextValueChild, type.get());
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addToken_CodeableConcept(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> codeableConceptDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("CodeableConcept");
|
||||
BaseRuntimeChildDefinition codeableConceptCodingValueChild = codeableConceptDefinition.getChildByName("coding");
|
||||
BaseRuntimeChildDefinition codeableConceptTextValueChild = codeableConceptDefinition.getChildByName("text");
|
||||
|
||||
List<IBase> codings = codeableConceptCodingValueChild.getAccessor().getValues(theValue);
|
||||
List<IBase> codings = myCodeableConceptCodingValueChild.getAccessor().getValues(theValue);
|
||||
for (IBase nextCoding : codings) {
|
||||
addToken_Coding(theResourceType, theParams, theSearchParam, nextCoding);
|
||||
}
|
||||
|
||||
String text = extractValueAsString(codeableConceptTextValueChild, theValue);
|
||||
String text = extractValueAsString(myCodeableConceptTextValueChild, theValue);
|
||||
if (isNotBlank(text)) {
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, text);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToken_Coding(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> codingDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Coding");
|
||||
BaseRuntimeChildDefinition codingSystemValueChild = codingDefinition.getChildByName("system");
|
||||
BaseRuntimeChildDefinition codingCodeValueChild = codingDefinition.getChildByName("code");
|
||||
BaseRuntimeChildDefinition codingDisplayValueChild = codingDefinition.getChildByName("display");
|
||||
|
||||
String system = extractValueAsString(codingSystemValueChild, theValue);
|
||||
String code = extractValueAsString(codingCodeValueChild, theValue);
|
||||
String system = extractValueAsString(myCodingSystemValueChild, theValue);
|
||||
String code = extractValueAsString(myCodingCodeValueChild, theValue);
|
||||
createTokenIndexIfNotBlank(theResourceType, theParams, theSearchParam, system, code);
|
||||
|
||||
String text = extractValueAsString(codingDisplayValueChild, theValue);
|
||||
String text = extractValueAsString(myCodingDisplayValueChild, theValue);
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, text);
|
||||
}
|
||||
|
||||
private void addToken_ContactPoint(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> contactPointDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("ContactPoint");
|
||||
BaseRuntimeChildDefinition contactPointSystemValueChild = contactPointDefinition.getChildByName("system");
|
||||
BaseRuntimeChildDefinition contactPointValueValueChild = contactPointDefinition.getChildByName("value");
|
||||
|
||||
String system = extractValueAsString(contactPointSystemValueChild, theValue);
|
||||
String value = extractValueAsString(contactPointValueValueChild, theValue);
|
||||
String system = extractValueAsString(myContactPointSystemValueChild, theValue);
|
||||
String value = extractValueAsString(myContactPointValueValueChild, theValue);
|
||||
createTokenIndexIfNotBlank(theResourceType, theParams, theSearchParam, system, value);
|
||||
}
|
||||
|
||||
private void addToken_PatientCommunication(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> patientDefinition = getContext().getResourceDefinition("Patient");
|
||||
BaseRuntimeChildDefinition patientCommunicationValueChild = patientDefinition.getChildByName("communication");
|
||||
BaseRuntimeElementCompositeDefinition<?> patientCommunicationDefinition = (BaseRuntimeElementCompositeDefinition<?>) patientCommunicationValueChild.getChildByName("communication");
|
||||
BaseRuntimeChildDefinition patientCommunicationLanguageValueChild = patientCommunicationDefinition.getChildByName("language");
|
||||
|
||||
List<IBase> values = patientCommunicationLanguageValueChild.getAccessor().getValues(theValue);
|
||||
List<IBase> values = myPatientCommunicationLanguageValueChild.getAccessor().getValues(theValue);
|
||||
for (IBase next : values) {
|
||||
addToken_CodeableConcept(theResourceType, theParams, theSearchParam, next);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToken_CapabilityStatementRestSecurity(String theResourceType, Set<BaseResourceIndexedSearchParam> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> capabilityStatementDefinition = getContext().getResourceDefinition("CapabilityStatement");
|
||||
BaseRuntimeChildDefinition capabilityStatementRestChild = capabilityStatementDefinition.getChildByName("rest");
|
||||
BaseRuntimeElementCompositeDefinition<?> capabilityStatementRestDefinition = (BaseRuntimeElementCompositeDefinition<?>) capabilityStatementRestChild.getChildByName("rest");
|
||||
BaseRuntimeChildDefinition capabilityStatementRestSecurityValueChild = capabilityStatementRestDefinition.getChildByName("security");
|
||||
BaseRuntimeElementCompositeDefinition<?> capabilityStatementRestSecurityDefinition = (BaseRuntimeElementCompositeDefinition<?>) capabilityStatementRestSecurityValueChild.getChildByName("security");
|
||||
BaseRuntimeChildDefinition capabilityStatementRestSecurityServiceValueChild = capabilityStatementRestSecurityDefinition.getChildByName("service");
|
||||
|
||||
List<IBase> values = capabilityStatementRestSecurityServiceValueChild.getAccessor().getValues(theValue);
|
||||
List<IBase> values = myCapabilityStatementRestSecurityServiceValueChild.getAccessor().getValues(theValue);
|
||||
for (IBase nextValue : values) {
|
||||
addToken_CodeableConcept(theResourceType, theParams, theSearchParam, nextValue);
|
||||
}
|
||||
|
@ -561,13 +540,9 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addDate_Period(String theResourceType, Set<ResourceIndexedSearchParamDate> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> periodDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Period");
|
||||
BaseRuntimeChildDefinition periodStartValueChild = periodDefinition.getChildByName("start");
|
||||
BaseRuntimeChildDefinition periodEndValueChild = periodDefinition.getChildByName("end");
|
||||
|
||||
Date start = extractValueAsDate(periodStartValueChild, theValue);
|
||||
String startAsString = extractValueAsString(periodStartValueChild, theValue);
|
||||
Date end = extractValueAsDate(periodEndValueChild, theValue);
|
||||
Date start = extractValueAsDate(myPeriodStartValueChild, theValue);
|
||||
String startAsString = extractValueAsString(myPeriodStartValueChild, theValue);
|
||||
Date end = extractValueAsDate(myPeriodEndValueChild, theValue);
|
||||
|
||||
if (start != null || end != null) {
|
||||
ResourceIndexedSearchParamDate nextEntity = new ResourceIndexedSearchParamDate(theResourceType, theSearchParam.getName(), start, end, startAsString);
|
||||
|
@ -576,13 +551,7 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addDate_Timing(String theResourceType, Set<ResourceIndexedSearchParamDate> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> timingDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Timing");
|
||||
BaseRuntimeChildDefinition timingEventValueChild = timingDefinition.getChildByName("event");
|
||||
BaseRuntimeChildDefinition timingRepeatValueChild = timingDefinition.getChildByName("repeat");
|
||||
BaseRuntimeElementCompositeDefinition<?> timingRepeatDefinition = (BaseRuntimeElementCompositeDefinition<?>) timingRepeatValueChild.getChildByName("repeat");
|
||||
BaseRuntimeChildDefinition timingRepeatBoundsValueChild = timingRepeatDefinition.getChildByName("bounds[x]");
|
||||
|
||||
List<IPrimitiveType<Date>> values = extractValuesAsFhirDates(timingEventValueChild, theValue);
|
||||
List<IPrimitiveType<Date>> values = extractValuesAsFhirDates(myTimingEventValueChild, theValue);
|
||||
|
||||
TreeSet<Date> dates = new TreeSet<>();
|
||||
String firstValue = null;
|
||||
|
@ -595,21 +564,16 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
}
|
||||
|
||||
Optional<IBase> repeat = timingRepeatValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
Optional<IBase> repeat = myTimingRepeatValueChild.getAccessor().getFirstValueOrNull(theValue);
|
||||
if (repeat.isPresent()) {
|
||||
Optional<IBase> bounds = timingRepeatBoundsValueChild.getAccessor().getFirstValueOrNull(repeat.get());
|
||||
Optional<IBase> bounds = myTimingRepeatBoundsValueChild.getAccessor().getFirstValueOrNull(repeat.get());
|
||||
if (bounds.isPresent()) {
|
||||
String boundsType = toRootTypeName(bounds.get());
|
||||
switch (boundsType) {
|
||||
case "Period":
|
||||
BaseRuntimeElementCompositeDefinition<?> periodDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Period");
|
||||
BaseRuntimeChildDefinition periodStartValueChild = periodDefinition.getChildByName("start");
|
||||
BaseRuntimeChildDefinition periodEndValueChild = periodDefinition.getChildByName("end");
|
||||
Date start = extractValueAsDate(periodStartValueChild, bounds.get());
|
||||
Date end = extractValueAsDate(periodEndValueChild, bounds.get());
|
||||
dates.add(start);
|
||||
dates.add(end);
|
||||
break;
|
||||
if ("Period".equals(boundsType)) {
|
||||
Date start = extractValueAsDate(myPeriodStartValueChild, bounds.get());
|
||||
Date end = extractValueAsDate(myPeriodEndValueChild, bounds.get());
|
||||
dates.add(start);
|
||||
dates.add(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -621,14 +585,9 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addNumber_Duration(String theResourceType, Set<ResourceIndexedSearchParamNumber> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> durationDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Duration");
|
||||
BaseRuntimeChildDefinition durationSystemValueChild = durationDefinition.getChildByName("system");
|
||||
BaseRuntimeChildDefinition durationCodeValueChild = durationDefinition.getChildByName("code");
|
||||
BaseRuntimeChildDefinition durationValueValueChild = durationDefinition.getChildByName("value");
|
||||
|
||||
String system = extractValueAsString(durationSystemValueChild, theValue);
|
||||
String code = extractValueAsString(durationCodeValueChild, theValue);
|
||||
BigDecimal value = extractValueAsBigDecimal(durationValueValueChild, theValue);
|
||||
String system = extractValueAsString(myDurationSystemValueChild, theValue);
|
||||
String code = extractValueAsString(myDurationCodeValueChild, theValue);
|
||||
BigDecimal value = extractValueAsBigDecimal(myDurationValueValueChild, theValue);
|
||||
if (value != null) {
|
||||
value = normalizeQuantityContainingTimeUnitsIntoDaysForNumberParam(system, code, value);
|
||||
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(theResourceType, theSearchParam.getName(), value);
|
||||
|
@ -637,15 +596,10 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addNumber_Quantity(String theResourceType, Set<ResourceIndexedSearchParamNumber> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> quantityDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Duration");
|
||||
BaseRuntimeChildDefinition quantityValueValueChild = quantityDefinition.getChildByName("value");
|
||||
BaseRuntimeChildDefinition quantitySystemChild = quantityDefinition.getChildByName("system");
|
||||
BaseRuntimeChildDefinition quantityCodeChild = quantityDefinition.getChildByName("code");
|
||||
|
||||
BigDecimal value = extractValueAsBigDecimal(quantityValueValueChild, theValue);
|
||||
BigDecimal value = extractValueAsBigDecimal(myQuantityValueValueChild, theValue);
|
||||
if (value != null) {
|
||||
String system = extractValueAsString(quantitySystemChild, theValue);
|
||||
String code = extractValueAsString(quantityCodeChild, theValue);
|
||||
String system = extractValueAsString(myQuantitySystemValueChild, theValue);
|
||||
String code = extractValueAsString(myQuantityCodeValueChild, theValue);
|
||||
value = normalizeQuantityContainingTimeUnitsIntoDaysForNumberParam(system, code, value);
|
||||
ResourceIndexedSearchParamNumber nextEntity = new ResourceIndexedSearchParamNumber(theResourceType, theSearchParam.getName(), value);
|
||||
theParams.add(nextEntity);
|
||||
|
@ -675,16 +629,12 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addString_HumanName(String theResourceType, Set<ResourceIndexedSearchParamString> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> humanNameDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("HumanName");
|
||||
BaseRuntimeChildDefinition humanNameFamilyValueChild = humanNameDefinition.getChildByName("family");
|
||||
BaseRuntimeChildDefinition humanNameGivenValueChild = humanNameDefinition.getChildByName("given");
|
||||
|
||||
List<String> families = extractValuesAsStrings(humanNameFamilyValueChild, theValue);
|
||||
List<String> families = extractValuesAsStrings(myHumanNameFamilyValueChild, theValue);
|
||||
for (String next : families) {
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, next);
|
||||
}
|
||||
|
||||
List<String> givens = extractValuesAsStrings(humanNameGivenValueChild, theValue);
|
||||
List<String> givens = extractValuesAsStrings(myHumanNameGivenValueChild, theValue);
|
||||
for (String next : givens) {
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, next);
|
||||
}
|
||||
|
@ -692,61 +642,48 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
private void addString_Quantity(String theResourceType, Set<ResourceIndexedSearchParamString> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> quantityDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Quantity");
|
||||
BaseRuntimeChildDefinition quantityValueChild = quantityDefinition.getChildByName("value");
|
||||
|
||||
BigDecimal value = extractValueAsBigDecimal(quantityValueChild, theValue);
|
||||
BigDecimal value = extractValueAsBigDecimal(myQuantityValueValueChild, theValue);
|
||||
if (value != null) {
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, value.toPlainString());
|
||||
}
|
||||
}
|
||||
|
||||
private void addString_Range(String theResourceType, Set<ResourceIndexedSearchParamString> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> rangeDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Range");
|
||||
BaseRuntimeChildDefinition rangeLowValueChild = rangeDefinition.getChildByName("low");
|
||||
|
||||
BigDecimal value = extractValueAsBigDecimal(rangeLowValueChild, theValue);
|
||||
BigDecimal value = extractValueAsBigDecimal(myRangeLowValueChild, theValue);
|
||||
if (value != null) {
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, value.toPlainString());
|
||||
}
|
||||
}
|
||||
|
||||
private void addString_ContactPoint(String theResourceType, Set<ResourceIndexedSearchParamString> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> contactPointDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("ContactPoint");
|
||||
BaseRuntimeChildDefinition contactPointValueValueChild = contactPointDefinition.getChildByName("value");
|
||||
|
||||
String value = extractValueAsString(contactPointValueValueChild, theValue);
|
||||
String value = extractValueAsString(myContactPointValueValueChild, theValue);
|
||||
if (isNotBlank(value)) {
|
||||
createStringIndexIfNotBlank(theResourceType, theParams, theSearchParam, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void addString_Address(String theResourceType, Set<ResourceIndexedSearchParamString> theParams, RuntimeSearchParam theSearchParam, IBase theValue) {
|
||||
BaseRuntimeElementCompositeDefinition<?> addressDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Address");
|
||||
BaseRuntimeChildDefinition addressLineValueChild = addressDefinition.getChildByName("line");
|
||||
BaseRuntimeChildDefinition addressCityValueChild = addressDefinition.getChildByName("city");
|
||||
BaseRuntimeChildDefinition addressStateValueChild = addressDefinition.getChildByName("state");
|
||||
BaseRuntimeChildDefinition addressCountryValueChild = addressDefinition.getChildByName("country");
|
||||
BaseRuntimeChildDefinition addressPostalCodeValueChild = addressDefinition.getChildByName("postalCode");
|
||||
|
||||
List<String> allNames = new ArrayList<>(extractValuesAsStrings(addressLineValueChild, theValue));
|
||||
List<String> allNames = new ArrayList<>(extractValuesAsStrings(myAddressLineValueChild, theValue));
|
||||
|
||||
String city = extractValueAsString(addressCityValueChild, theValue);
|
||||
String city = extractValueAsString(myAddressCityValueChild, theValue);
|
||||
if (isNotBlank(city)) {
|
||||
allNames.add(city);
|
||||
}
|
||||
|
||||
String state = extractValueAsString(addressStateValueChild, theValue);
|
||||
String state = extractValueAsString(myAddressStateValueChild, theValue);
|
||||
if (isNotBlank(state)) {
|
||||
allNames.add(state);
|
||||
}
|
||||
|
||||
String country = extractValueAsString(addressCountryValueChild, theValue);
|
||||
String country = extractValueAsString(myAddressCountryValueChild, theValue);
|
||||
if (isNotBlank(country)) {
|
||||
allNames.add(country);
|
||||
}
|
||||
|
||||
String postalCode = extractValueAsString(addressPostalCodeValueChild, theValue);
|
||||
String postalCode = extractValueAsString(myAddressPostalCodeValueChild, theValue);
|
||||
if (isNotBlank(postalCode)) {
|
||||
allNames.add(postalCode);
|
||||
}
|
||||
|
@ -758,8 +695,8 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
}
|
||||
|
||||
|
||||
private <T extends BaseResourceIndexedSearchParam> Set<T> extractSearchParams(IBaseResource theResource, IExtractor<T> theExtractor, RestSearchParameterTypeEnum theSearchParamType) {
|
||||
Set<T> retVal = new HashSet<>();
|
||||
private <T extends BaseResourceIndexedSearchParam> SearchParamSet<T> extractSearchParams(IBaseResource theResource, IExtractor<T> theExtractor, RestSearchParameterTypeEnum theSearchParamType) {
|
||||
SearchParamSet<T> retVal = new SearchParamSet<>();
|
||||
|
||||
Collection<RuntimeSearchParam> searchParams = getSearchParams(theResource);
|
||||
for (RuntimeSearchParam nextSpDef : searchParams) {
|
||||
|
@ -874,19 +811,119 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
return theValue;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
myIgnoredForSearchDatatypes = new HashSet<>();
|
||||
addIgnoredType(getContext(), "Annotation", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Attachment", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Count", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Distance", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Ratio", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "SampledData", myIgnoredForSearchDatatypes);
|
||||
addIgnoredType(getContext(), "Signature", myIgnoredForSearchDatatypes);
|
||||
|
||||
/*
|
||||
* This is building up an internal map of all the various field accessors we'll need in order to work
|
||||
* with the model. This is kind of ugly, but we want to be as efficient as possible since
|
||||
* search param extraction happens a whole heck of a lot at runtime..
|
||||
*/
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> quantityDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Quantity");
|
||||
myQuantityValueValueChild = quantityDefinition.getChildByName("value");
|
||||
myQuantitySystemValueChild = quantityDefinition.getChildByName("system");
|
||||
myQuantityCodeValueChild = quantityDefinition.getChildByName("code");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> moneyDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Money");
|
||||
myMoneyValueChild = moneyDefinition.getChildByName("value");
|
||||
myMoneyCurrencyChild = moneyDefinition.getChildByName("currency");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> locationDefinition = getContext().getResourceDefinition("Location");
|
||||
BaseRuntimeChildDefinition locationPositionValueChild = locationDefinition.getChildByName("position");
|
||||
myLocationPositionDefinition = (BaseRuntimeElementCompositeDefinition<?>) locationPositionValueChild.getChildByName("position");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> codeSystemDefinition;
|
||||
if (getContext().getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.DSTU3)) {
|
||||
codeSystemDefinition = getContext().getResourceDefinition("CodeSystem");
|
||||
assert codeSystemDefinition != null;
|
||||
myCodeSystemUrlValueChild = codeSystemDefinition.getChildByName("url");
|
||||
}
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> rangeDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Range");
|
||||
myRangeLowValueChild = rangeDefinition.getChildByName("low");
|
||||
myRangeHighValueChild = rangeDefinition.getChildByName("high");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> addressDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Address");
|
||||
myAddressLineValueChild = addressDefinition.getChildByName("line");
|
||||
myAddressCityValueChild = addressDefinition.getChildByName("city");
|
||||
myAddressStateValueChild = addressDefinition.getChildByName("state");
|
||||
myAddressCountryValueChild = addressDefinition.getChildByName("country");
|
||||
myAddressPostalCodeValueChild = addressDefinition.getChildByName("postalCode");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> capabilityStatementDefinition = getContext().getResourceDefinition("CapabilityStatement");
|
||||
BaseRuntimeChildDefinition capabilityStatementRestChild = capabilityStatementDefinition.getChildByName("rest");
|
||||
BaseRuntimeElementCompositeDefinition<?> capabilityStatementRestDefinition = (BaseRuntimeElementCompositeDefinition<?>) capabilityStatementRestChild.getChildByName("rest");
|
||||
BaseRuntimeChildDefinition capabilityStatementRestSecurityValueChild = capabilityStatementRestDefinition.getChildByName("security");
|
||||
BaseRuntimeElementCompositeDefinition<?> capabilityStatementRestSecurityDefinition = (BaseRuntimeElementCompositeDefinition<?>) capabilityStatementRestSecurityValueChild.getChildByName("security");
|
||||
myCapabilityStatementRestSecurityServiceValueChild = capabilityStatementRestSecurityDefinition.getChildByName("service");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> periodDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Period");
|
||||
myPeriodStartValueChild = periodDefinition.getChildByName("start");
|
||||
myPeriodEndValueChild = periodDefinition.getChildByName("end");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> timingDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Timing");
|
||||
myTimingEventValueChild = timingDefinition.getChildByName("event");
|
||||
myTimingRepeatValueChild = timingDefinition.getChildByName("repeat");
|
||||
BaseRuntimeElementCompositeDefinition<?> timingRepeatDefinition = (BaseRuntimeElementCompositeDefinition<?>) myTimingRepeatValueChild.getChildByName("repeat");
|
||||
myTimingRepeatBoundsValueChild = timingRepeatDefinition.getChildByName("bounds[x]");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> durationDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Duration");
|
||||
myDurationSystemValueChild = durationDefinition.getChildByName("system");
|
||||
myDurationCodeValueChild = durationDefinition.getChildByName("code");
|
||||
myDurationValueValueChild = durationDefinition.getChildByName("value");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> humanNameDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("HumanName");
|
||||
myHumanNameFamilyValueChild = humanNameDefinition.getChildByName("family");
|
||||
myHumanNameGivenValueChild = humanNameDefinition.getChildByName("given");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> contactPointDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("ContactPoint");
|
||||
myContactPointValueValueChild = contactPointDefinition.getChildByName("value");
|
||||
myContactPointSystemValueChild = contactPointDefinition.getChildByName("system");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> identifierDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Identifier");
|
||||
myIdentifierSystemValueChild = identifierDefinition.getChildByName("system");
|
||||
myIdentifierValueValueChild = identifierDefinition.getChildByName("value");
|
||||
myIdentifierTypeValueChild = identifierDefinition.getChildByName("type");
|
||||
BaseRuntimeElementCompositeDefinition<?> identifierTypeDefinition = (BaseRuntimeElementCompositeDefinition<?>) myIdentifierTypeValueChild.getChildByName("type");
|
||||
myIdentifierTypeTextValueChild = identifierTypeDefinition.getChildByName("text");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> codeableConceptDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("CodeableConcept");
|
||||
myCodeableConceptCodingValueChild = codeableConceptDefinition.getChildByName("coding");
|
||||
myCodeableConceptTextValueChild = codeableConceptDefinition.getChildByName("text");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> codingDefinition = (BaseRuntimeElementCompositeDefinition<?>) getContext().getElementDefinition("Coding");
|
||||
myCodingSystemValueChild = codingDefinition.getChildByName("system");
|
||||
myCodingCodeValueChild = codingDefinition.getChildByName("code");
|
||||
myCodingDisplayValueChild = codingDefinition.getChildByName("display");
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> patientDefinition = getContext().getResourceDefinition("Patient");
|
||||
BaseRuntimeChildDefinition patientCommunicationValueChild = patientDefinition.getChildByName("communication");
|
||||
BaseRuntimeElementCompositeDefinition<?> patientCommunicationDefinition = (BaseRuntimeElementCompositeDefinition<?>) patientCommunicationValueChild.getChildByName("communication");
|
||||
myPatientCommunicationLanguageValueChild = patientCommunicationDefinition.getChildByName("language");
|
||||
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IValueExtractor {
|
||||
|
||||
List<? extends IBase> get() throws FHIRException;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface IExtractor<T> {
|
||||
|
||||
|
||||
void extract(Set<T> theParams, RuntimeSearchParam theSearchParam, IBase theValue, String thePath);
|
||||
void extract(SearchParamSet<T> theParams, RuntimeSearchParam theSearchParam, IBase theValue, String thePath);
|
||||
|
||||
}
|
||||
|
||||
|
@ -946,5 +983,4 @@ public abstract class BaseSearchParamExtractor implements ISearchParamExtractor
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@ import ca.uhn.fhir.context.RuntimeSearchParam;
|
|||
import ca.uhn.fhir.jpa.model.entity.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -29,21 +28,44 @@ import java.util.Set;
|
|||
|
||||
public interface ISearchParamExtractor {
|
||||
|
||||
Set<ResourceIndexedSearchParamCoords> extractSearchParamCoords(IBaseResource theResource);
|
||||
SearchParamSet<ResourceIndexedSearchParamCoords> extractSearchParamCoords(IBaseResource theResource);
|
||||
|
||||
Set<ResourceIndexedSearchParamDate> extractSearchParamDates(IBaseResource theResource);
|
||||
SearchParamSet<ResourceIndexedSearchParamDate> extractSearchParamDates(IBaseResource theResource);
|
||||
|
||||
Set<ResourceIndexedSearchParamNumber> extractSearchParamNumber(IBaseResource theResource);
|
||||
SearchParamSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(IBaseResource theResource);
|
||||
|
||||
Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource);
|
||||
SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource);
|
||||
|
||||
Set<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource);
|
||||
SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource);
|
||||
|
||||
Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource);
|
||||
SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource);
|
||||
|
||||
Set<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource);
|
||||
SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource);
|
||||
|
||||
List<PathAndRef> extractResourceLinks(IBaseResource theResource, RuntimeSearchParam theNextSpDef);
|
||||
|
||||
String[] split(String theExpression);
|
||||
|
||||
|
||||
class SearchParamSet<T> extends HashSet<T> {
|
||||
|
||||
private List<String> myWarnings;
|
||||
|
||||
public void addWarning(String theWarning) {
|
||||
if (myWarnings == null) {
|
||||
myWarnings = new ArrayList<>();
|
||||
}
|
||||
myWarnings.add(theWarning);
|
||||
}
|
||||
|
||||
List<String> getWarnings() {
|
||||
if (myWarnings == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return myWarnings;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,14 +20,21 @@ package ca.uhn.fhir.jpa.searchparam.extractor;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.model.entity.*;
|
||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
@Service
|
||||
@Lazy
|
||||
|
@ -36,14 +43,33 @@ public class SearchParamExtractorService {
|
|||
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
@Autowired
|
||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
|
||||
public void extractFromResource(ResourceIndexedSearchParams theParams, ResourceTable theEntity, IBaseResource theResource) {
|
||||
theParams.myStringParams.addAll(extractSearchParamStrings(theResource));
|
||||
theParams.myNumberParams.addAll(extractSearchParamNumber(theResource));
|
||||
theParams.myQuantityParams.addAll(extractSearchParamQuantity(theResource));
|
||||
theParams.myDateParams.addAll(extractSearchParamDates(theResource));
|
||||
theParams.myUriParams.addAll(extractSearchParamUri(theResource));
|
||||
theParams.myCoordsParams.addAll(extractSearchParamCoords(theResource));
|
||||
public void extractFromResource(RequestDetails theRequestDetails, ResourceIndexedSearchParams theParams, ResourceTable theEntity, IBaseResource theResource) {
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> strings = extractSearchParamStrings(theResource);
|
||||
handleWarnings(theRequestDetails, strings);
|
||||
theParams.myStringParams.addAll(strings);
|
||||
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> numbers = extractSearchParamNumber(theResource);
|
||||
handleWarnings(theRequestDetails, numbers);
|
||||
theParams.myNumberParams.addAll(numbers);
|
||||
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> quantities = extractSearchParamQuantity(theResource);
|
||||
handleWarnings(theRequestDetails, quantities);
|
||||
theParams.myQuantityParams.addAll(quantities);
|
||||
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> dates = extractSearchParamDates(theResource);
|
||||
handleWarnings(theRequestDetails, dates);
|
||||
theParams.myDateParams.addAll(dates);
|
||||
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> uris = extractSearchParamUri(theResource);
|
||||
handleWarnings(theRequestDetails, uris);
|
||||
theParams.myUriParams.addAll(uris);
|
||||
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamCoords> coords = extractSearchParamCoords(theResource);
|
||||
handleWarnings(theRequestDetails, coords);
|
||||
theParams.myCoordsParams.addAll(coords);
|
||||
|
||||
ourLog.trace("Storing date indexes: {}", theParams.myDateParams);
|
||||
|
||||
|
@ -64,40 +90,60 @@ public class SearchParamExtractorService {
|
|||
populateResourceTable(theParams.myTokenParams, theEntity);
|
||||
}
|
||||
|
||||
void handleWarnings(RequestDetails theRequestDetails, ISearchParamExtractor.SearchParamSet<?> theSearchParamSet) {
|
||||
if (theSearchParamSet.getWarnings().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If extraction generated any warnings, broadcast an error
|
||||
for (String next : theSearchParamSet.getWarnings()) {
|
||||
StorageProcessingMessage messageHolder = new StorageProcessingMessage();
|
||||
messageHolder.setMessage(next);
|
||||
HookParams params = new HookParams()
|
||||
.add(RequestDetails.class, theRequestDetails)
|
||||
.addIfMatchesType(ServletRequestDetails.class, theRequestDetails)
|
||||
.add(StorageProcessingMessage.class, messageHolder);
|
||||
JpaInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequestDetails, Pointcut.JPA_PERFTRACE_WARNING, params);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateResourceTable(Collection<? extends BaseResourceIndexedSearchParam> theParams, ResourceTable theResourceTable) {
|
||||
for (BaseResourceIndexedSearchParam next : theParams) {
|
||||
next.setResource(theResourceTable);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<ResourceIndexedSearchParamCoords> extractSearchParamCoords(IBaseResource theResource) {
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamCoords> extractSearchParamCoords(IBaseResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamCoords(theResource);
|
||||
}
|
||||
|
||||
private Set<ResourceIndexedSearchParamDate> extractSearchParamDates(IBaseResource theResource) {
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> extractSearchParamDates(IBaseResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamDates(theResource);
|
||||
}
|
||||
|
||||
private Set<ResourceIndexedSearchParamNumber> extractSearchParamNumber(IBaseResource theResource) {
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> extractSearchParamNumber(IBaseResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamNumber(theResource);
|
||||
}
|
||||
|
||||
private Set<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource) {
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> extractSearchParamQuantity(IBaseResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamQuantity(theResource);
|
||||
}
|
||||
|
||||
private Set<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource) {
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> extractSearchParamStrings(IBaseResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamStrings(theResource);
|
||||
}
|
||||
|
||||
private Set<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource) {
|
||||
private ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> extractSearchParamTokens(IBaseResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamTokens(theResource);
|
||||
}
|
||||
|
||||
private Set<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource) {
|
||||
private ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> extractSearchParamUri(IBaseResource theResource) {
|
||||
return mySearchParamExtractor.extractSearchParamUri(theResource);
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
void setInterceptorBroadcasterForUnitTest(IInterceptorBroadcaster theJpaInterceptorBroadcaster) {
|
||||
myInterceptorBroadcaster = theJpaInterceptorBroadcaster;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class IndexedSearchParamExtractor {
|
|||
String resourceType = myContext.getResourceDefinition(theResource).getName();
|
||||
entity.setResourceType(resourceType);
|
||||
ResourceIndexedSearchParams resourceIndexedSearchParams = new ResourceIndexedSearchParams();
|
||||
mySearchParamExtractorService.extractFromResource(resourceIndexedSearchParams, entity, theResource);
|
||||
mySearchParamExtractorService.extractFromResource(theRequest, resourceIndexedSearchParams, entity, theResource);
|
||||
myResourceLinkExtractor.extractResourceLinks(resourceIndexedSearchParams, entity, theResource, theResource.getMeta().getLastUpdated(), myInlineResourceLinkResolver, false, theRequest);
|
||||
return resourceIndexedSearchParams;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,10 @@ import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
|||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.DefaultProfileValidationSupport;
|
||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
@ -25,7 +25,8 @@ import java.util.*;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.contains;
|
||||
|
||||
public class SearchParamExtractorDstu3Test {
|
||||
|
||||
|
@ -146,63 +147,42 @@ public class SearchParamExtractorDstu3Test {
|
|||
SearchParamExtractorDstu3 extractor = new SearchParamExtractorDstu3(new ModelConfig(), ourCtx, ourValidationSupport, searchParamRegistry);
|
||||
extractor.start();
|
||||
|
||||
try {
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.STRING, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||
Patient resource = new Patient();
|
||||
extractor.extractSearchParamStrings(resource);
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient", e.getMessage());
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamString> outcome = extractor.extractSearchParamStrings(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
|
||||
try {
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.TOKEN, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||
Patient resource = new Patient();
|
||||
extractor.extractSearchParamTokens(resource);
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient", e.getMessage());
|
||||
ISearchParamExtractor.SearchParamSet<BaseResourceIndexedSearchParam> outcome = extractor.extractSearchParamTokens(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
|
||||
try {
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.QUANTITY, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||
Patient resource = new Patient();
|
||||
extractor.extractSearchParamQuantity(resource);
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient", e.getMessage());
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamQuantity> outcome = extractor.extractSearchParamQuantity(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
|
||||
try {
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.DATE, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||
Patient resource = new Patient();
|
||||
extractor.extractSearchParamDates(resource);
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient", e.getMessage());
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamDate> outcome = extractor.extractSearchParamDates(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
|
||||
try {
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.NUMBER, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||
Patient resource = new Patient();
|
||||
extractor.extractSearchParamNumber(resource);
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient", e.getMessage());
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamNumber> outcome = extractor.extractSearchParamNumber(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
|
||||
try {
|
||||
{
|
||||
searchParamRegistry.addSearchParam(new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.URI, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE));
|
||||
Patient resource = new Patient();
|
||||
extractor.extractSearchParamUri(resource);
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient", e.getMessage());
|
||||
ISearchParamExtractor.SearchParamSet<ResourceIndexedSearchParamUri> outcome = extractor.extractSearchParamUri(resource);
|
||||
assertThat(outcome.getWarnings(), Matchers.contains("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient"));
|
||||
}
|
||||
|
||||
try {
|
||||
RuntimeSearchParam sp = new RuntimeSearchParam("foo", "foo", "Patient", RestSearchParameterTypeEnum.REFERENCE, Sets.newHashSet(), Sets.newHashSet(), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE);
|
||||
searchParamRegistry.addSearchParam(sp);
|
||||
Patient resource = new Patient();
|
||||
extractor.extractResourceLinks(resource, sp);
|
||||
} catch (ConfigurationException e) {
|
||||
assertEquals("Search param foo is of unexpected datatype: class org.hl7.fhir.dstu3.model.Patient", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package ca.uhn.fhir.jpa.searchparam.extractor;
|
||||
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SearchParamExtractorServiceTest {
|
||||
|
||||
private SearchParamExtractorService mySvc;
|
||||
@Mock
|
||||
private IInterceptorBroadcaster myRequestInterceptorBroadcaster;
|
||||
@Mock
|
||||
private IInterceptorBroadcaster myJpaInterceptorBroadcaster;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
mySvc = new SearchParamExtractorService();
|
||||
mySvc.setInterceptorBroadcasterForUnitTest(myJpaInterceptorBroadcaster);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleWarnings() {
|
||||
ISearchParamExtractor.SearchParamSet<Object> searchParamSet = new ISearchParamExtractor.SearchParamSet<>();
|
||||
searchParamSet.addWarning("help i'm a bug");
|
||||
searchParamSet.addWarning("Spiff");
|
||||
|
||||
when(myJpaInterceptorBroadcaster.callHooks(any(), any())).thenReturn(true);
|
||||
|
||||
mySvc.handleWarnings(new ServletRequestDetails(myRequestInterceptorBroadcaster), searchParamSet);
|
||||
|
||||
verify(myJpaInterceptorBroadcaster, times(2)).callHooks(eq(Pointcut.JPA_PERFTRACE_WARNING), any());
|
||||
verify(myRequestInterceptorBroadcaster, times(2)).callHooks(eq(Pointcut.JPA_PERFTRACE_WARNING), any());
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
@ -50,7 +52,17 @@ public class SubscriptionLoaderTest extends BaseBlockingQueueSubscribableChannel
|
|||
@Test
|
||||
public void testMultipleThreadsDontBlock() throws InterruptedException {
|
||||
SubscriptionLoader svc = new SubscriptionLoader();
|
||||
svc.acquireSemaphoreForUnitTest();
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
new Thread(()->{
|
||||
try {
|
||||
svc.acquireSemaphoreForUnitTest();
|
||||
latch.countDown();
|
||||
} catch (InterruptedException theE) {
|
||||
// ignore
|
||||
}
|
||||
}).start();
|
||||
|
||||
latch.await(10, TimeUnit.SECONDS);
|
||||
svc.syncSubscriptions();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
<artifactId>hapi-fhir-testpage-overlay</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>classes</classifier>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -140,8 +140,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
if (Constants.PARAM_HISTORY.equals(theRequest.getOperation())) {
|
||||
if (mySupportsVersion == false) {
|
||||
return false;
|
||||
}
|
||||
if (theRequest.getId().hasVersionIdPart() == false) {
|
||||
} else if (theRequest.getId().hasVersionIdPart() == false) {
|
||||
return false;
|
||||
}
|
||||
} else if (!StringUtils.isBlank(theRequest.getOperation())) {
|
||||
|
|
|
@ -101,6 +101,31 @@ public class ReadMethodBindingTest {
|
|||
when(myRequestDetails.getOperation()).thenReturn("$foo");
|
||||
assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
||||
|
||||
// History operation
|
||||
when(myRequestDetails.getId()).thenReturn(new IdDt("Patient/123"));
|
||||
when(myRequestDetails.getOperation()).thenReturn("_history");
|
||||
assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncomingServerRequestNoMatch_HasCompartment() throws NoSuchMethodException {
|
||||
|
||||
class MyProvider {
|
||||
@Read(version = false)
|
||||
public IBaseResource read(@IdParam IIdType theIdType) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
when(myCtx.getResourceDefinition(any(Class.class))).thenReturn(definition);
|
||||
when(definition.getName()).thenReturn("Patient");
|
||||
when(myRequestDetails.getResourceName()).thenReturn("Patient");
|
||||
when(myRequestDetails.getCompartmentName()).thenReturn("Patient");
|
||||
when(myRequestDetails.getId()).thenReturn(new IdDt("Patient/123"));
|
||||
|
||||
ReadMethodBinding binding = createBinding(new MyProvider());
|
||||
assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
||||
}
|
||||
|
||||
public ReadMethodBinding createBinding(Object theProvider) throws NoSuchMethodException {
|
||||
|
|
|
@ -9,7 +9,10 @@ import ca.uhn.fhir.rest.annotation.Metadata;
|
|||
import ca.uhn.fhir.rest.annotation.Read;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.server.*;
|
||||
import ca.uhn.fhir.rest.server.Bindings;
|
||||
import ca.uhn.fhir.rest.server.IServerConformanceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.RestfulServerConfiguration;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.method.*;
|
||||
import ca.uhn.fhir.rest.server.method.SearchParameter;
|
||||
|
@ -113,7 +116,6 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
|
||||
|
||||
|
||||
private DateTimeType conformanceDate(RequestDetails theRequestDetails) {
|
||||
IPrimitiveType<Date> buildDate = getServerConfiguration(theRequestDetails).getConformanceDate();
|
||||
if (buildDate != null && buildDate.getValue() != null) {
|
||||
|
@ -127,7 +129,6 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the "publisher" that will be placed in the generated conformance statement. As this is a mandatory element, the value should not be null (although this is not enforced). The
|
||||
* value defaults to "Not provided" but may be set to null, which will cause this element to be omitted.
|
||||
|
@ -194,47 +195,46 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
// Map<String, CapabilityStatement.RestResourceSearchParam> nameToSearchParam = new HashMap<String,
|
||||
// CapabilityStatement.RestResourceSearchParam>();
|
||||
for (BaseMethodBinding<?> nextMethodBinding : nextEntry.getValue()) {
|
||||
if (nextMethodBinding.getRestOperationType() != null) {
|
||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||
if (resOpCode != null) {
|
||||
TypeRestfulInteraction resOp;
|
||||
try {
|
||||
resOp = TypeRestfulInteraction.fromCode(resOpCode);
|
||||
} catch (Exception e) {
|
||||
resOp = null;
|
||||
nextMethodBinding.getRestOperationType();
|
||||
String resOpCode = nextMethodBinding.getRestOperationType().getCode();
|
||||
if (resOpCode != null) {
|
||||
TypeRestfulInteraction resOp;
|
||||
try {
|
||||
resOp = TypeRestfulInteraction.fromCode(resOpCode);
|
||||
} catch (Exception e) {
|
||||
resOp = null;
|
||||
}
|
||||
if (resOp != null) {
|
||||
if (resourceOps.contains(resOp) == false) {
|
||||
resourceOps.add(resOp);
|
||||
resource.addInteraction().setCode(resOp);
|
||||
}
|
||||
if (resOp != null) {
|
||||
if ("vread".equals(resOpCode)) {
|
||||
// vread implies read
|
||||
resOp = TypeRestfulInteraction.READ;
|
||||
if (resourceOps.contains(resOp) == false) {
|
||||
resourceOps.add(resOp);
|
||||
resource.addInteraction().setCode(resOp);
|
||||
}
|
||||
if ("vread".equals(resOpCode)) {
|
||||
// vread implies read
|
||||
resOp = TypeRestfulInteraction.READ;
|
||||
if (resourceOps.contains(resOp) == false) {
|
||||
resourceOps.add(resOp);
|
||||
resource.addInteraction().setCode(resOp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nextMethodBinding.isSupportsConditional()) {
|
||||
switch (resOp) {
|
||||
case CREATE:
|
||||
resource.setConditionalCreate(true);
|
||||
break;
|
||||
case DELETE:
|
||||
if (nextMethodBinding.isSupportsConditionalMultiple()) {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.MULTIPLE);
|
||||
} else {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
}
|
||||
break;
|
||||
case UPDATE:
|
||||
resource.setConditionalUpdate(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (nextMethodBinding.isSupportsConditional()) {
|
||||
switch (resOp) {
|
||||
case CREATE:
|
||||
resource.setConditionalCreate(true);
|
||||
break;
|
||||
case DELETE:
|
||||
if (nextMethodBinding.isSupportsConditionalMultiple()) {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.MULTIPLE);
|
||||
} else {
|
||||
resource.setConditionalDelete(ConditionalDeleteStatus.SINGLE);
|
||||
}
|
||||
break;
|
||||
case UPDATE:
|
||||
resource.setConditionalUpdate(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,28 +315,18 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
sortSearchParameters(searchParameters);
|
||||
if (!searchParameters.isEmpty()) {
|
||||
// boolean allOptional = searchParameters.get(0).isRequired() == false;
|
||||
//
|
||||
// OperationDefinition query = null;
|
||||
// if (!allOptional) {
|
||||
// RestOperation operation = rest.addOperation();
|
||||
// query = new OperationDefinition();
|
||||
// operation.setDefinition(new ResourceReferenceDt(query));
|
||||
// query.getDescriptionElement().setValue(searchMethodBinding.getDescription());
|
||||
// query.addUndeclaredExtension(false, ExtensionConstants.QUERY_RETURN_TYPE, new CodeDt(resourceName));
|
||||
// for (String nextInclude : searchMethodBinding.getIncludes()) {
|
||||
// query.addUndeclaredExtension(false, ExtensionConstants.QUERY_ALLOWED_INCLUDE, new StringDt(nextInclude));
|
||||
// }
|
||||
// }
|
||||
|
||||
for (SearchParameter nextParameter : searchParameters) {
|
||||
|
||||
if (nextParameter.getParamType() == null) {
|
||||
ourLog.warn("SearchParameter {}:{} does not declare a type - Not exporting in CapabilityStatement", def.getName(), nextParameter.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
String nextParamName = nextParameter.getName();
|
||||
|
||||
String chain = null;
|
||||
String nextParamUnchainedName = nextParamName;
|
||||
if (nextParamName.contains(".")) {
|
||||
chain = nextParamName.substring(nextParamName.indexOf('.') + 1);
|
||||
nextParamUnchainedName = nextParamName.substring(0, nextParamName.indexOf('.'));
|
||||
}
|
||||
|
||||
|
@ -352,45 +342,18 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
CapabilityStatementRestResourceSearchParamComponent param = resource.addSearchParam();
|
||||
String typeCode = nextParameter.getParamType().getCode();
|
||||
param.getTypeElement().setValueAsString(typeCode);
|
||||
param.setName(nextParamUnchainedName);
|
||||
|
||||
// if (StringUtils.isNotBlank(chain)) {
|
||||
// param.addChain(chain);
|
||||
// }
|
||||
//
|
||||
// if (nextParameter.getParamType() == RestSearchParameterTypeEnum.REFERENCE) {
|
||||
// for (String nextWhitelist : new TreeSet<String>(nextParameter.getQualifierWhitelist())) {
|
||||
// if (nextWhitelist.startsWith(".")) {
|
||||
// param.addChain(nextWhitelist.substring(1));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
param.setDocumentation(nextParamDescription);
|
||||
if (nextParameter.getParamType() != null) {
|
||||
param.getTypeElement().setValueAsString(nextParameter.getParamType().getCode());
|
||||
}
|
||||
for (Class<? extends IBaseResource> nextTarget : nextParameter.getDeclaredTypes()) {
|
||||
RuntimeResourceDefinition targetDef = getServerConfiguration(theRequestDetails).getFhirContext().getResourceDefinition(nextTarget);
|
||||
if (targetDef != null) {
|
||||
ResourceType code;
|
||||
try {
|
||||
code = ResourceType.fromCode(targetDef.getName());
|
||||
} catch (FHIRException e) {
|
||||
code = null;
|
||||
}
|
||||
// if (code != null) {
|
||||
// param.addTarget(targetDef.getName());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Read(type = OperationDefinition.class)
|
||||
public OperationDefinition readOperationDefinition(@IdParam IdType theId, RequestDetails theRequestDetails) {
|
||||
if (theId == null || theId.hasIdPart() == false) {
|
||||
|
|
|
@ -111,7 +111,11 @@ public class ValidatorWrapper {
|
|||
profileSet.getCanonical().add(new ValidationProfileSet.ProfileRegistration(nextProfile, true));
|
||||
}
|
||||
|
||||
v.validate(null, messages, document, profileSet);
|
||||
String resourceAsString = theValidationContext.getResourceAsString();
|
||||
InputStream inputStream = new ReaderInputStream(new StringReader(resourceAsString), Charsets.UTF_8);
|
||||
|
||||
Manager.FhirFormat format = Manager.FhirFormat.XML;
|
||||
v.validate(null, messages, inputStream, format, profileSet);
|
||||
|
||||
} else if (encoding == EncodingEnum.JSON) {
|
||||
|
||||
|
|
|
@ -799,6 +799,8 @@ public class FhirInstanceValidatorR4Test extends BaseTest {
|
|||
ourLog.info(output.getMessages().get(0).getMessage());
|
||||
assertEquals("/f:Patient", output.getMessages().get(0).getLocationString());
|
||||
assertEquals("Undefined element 'foo'", output.getMessages().get(0).getMessage());
|
||||
assertEquals(28, output.getMessages().get(0).getLocationCol().intValue());
|
||||
assertEquals(4, output.getMessages().get(0).getLocationLine().intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -476,6 +476,10 @@
|
|||
<action type="fix">
|
||||
Search parameters of type URI did not work in the hapi-fhir-testpage-overlay. This has been corrected.
|
||||
</action>
|
||||
<action type="fix" issue="1568">
|
||||
JPA servers accidentally stripped the type attribute from the server-exported CapabilityStatement
|
||||
when search parameters of type "special" were found. This has been corrected.
|
||||
</action>
|
||||
</release>
|
||||
<release version="4.0.3" date="2019-09-03" description="Igloo (Point Release)">
|
||||
<action type="fix">
|
||||
|
|
|
@ -262,6 +262,16 @@
|
|||
<td style="background: #CEC;">4.0.0</td>
|
||||
<td style="background: #EEB;">4.1.0-e0e3caf9ba</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAPI FHIR 4.1.0</td>
|
||||
<td>JDK8</td>
|
||||
<td style="background: #DDD;"></td>
|
||||
<td style="background: #CEC;">1.0.2</td>
|
||||
<td style="background: #EEB;">1.4.0</td>
|
||||
<td style="background: #CEC;">3.0.1</td>
|
||||
<td style="background: #CEC;">4.0.0</td>
|
||||
<td style="background: #EEB;">4.1.0-1a7623d866</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
|
||||
|
||||
mkdir -p hapi-tinder-plugin/src/main/resources/res/r5/
|
||||
rm hapi-tinder-plugin/src/main/resources/res/r5/*.xml; cp ~/git/fhir/source/*/*-spreadsheet.xml hapi-tinder-plugin/src/main/resources/res/r5/; rm hapi-tinder-plugin/src/main/resources/res/r5/*-*-*.xml
|
||||
|
||||
|
|
Loading…
Reference in New Issue