mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-02-16 18:05:19 +00:00
Performance enhancements on the CapabilityStatement generator for JPA
server
This commit is contained in:
parent
e299b062a6
commit
593a705365
@ -619,12 +619,14 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype<String>, */IIdTy
|
|||||||
/**
|
/**
|
||||||
* Creates a new instance of this ID which is identical, but refers to the specific version of this resource ID noted by theVersion.
|
* Creates a new instance of this ID which is identical, but refers to the specific version of this resource ID noted by theVersion.
|
||||||
*
|
*
|
||||||
* @param theVersion The actual version string, e.g. "1"
|
* @param theVersion The actual version string, e.g. "1". If theVersion is blank or null, returns the same as {@link #toVersionless()}}
|
||||||
* @return A new instance of IdDt which is identical, but refers to the specific version of this resource ID noted by theVersion.
|
* @return A new instance of IdDt which is identical, but refers to the specific version of this resource ID noted by theVersion.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IdDt withVersion(String theVersion) {
|
public IdDt withVersion(String theVersion) {
|
||||||
Validate.notBlank(theVersion, "Version may not be null or empty");
|
if (isBlank(theVersion)) {
|
||||||
|
return toVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
if (isLocal() || isUrn()) {
|
if (isLocal() || isUrn()) {
|
||||||
return new IdDt(getValueAsString());
|
return new IdDt(getValueAsString());
|
||||||
|
@ -4,8 +4,10 @@ import ca.uhn.fhir.context.FhirContext;
|
|||||||
import ca.uhn.fhir.jpa.dao.*;
|
import ca.uhn.fhir.jpa.dao.*;
|
||||||
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu2;
|
import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu2;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
||||||
|
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
import ca.uhn.fhir.validation.IValidatorModule;
|
import ca.uhn.fhir.validation.IValidatorModule;
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.hl7.fhir.instance.hapi.validation.DefaultProfileValidationSupport;
|
import org.hl7.fhir.instance.hapi.validation.DefaultProfileValidationSupport;
|
||||||
import org.hl7.fhir.instance.hapi.validation.FhirInstanceValidator;
|
import org.hl7.fhir.instance.hapi.validation.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.instance.hapi.validation.ValidationSupportChain;
|
import org.hl7.fhir.instance.hapi.validation.ValidationSupportChain;
|
||||||
@ -17,6 +19,8 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JPA Server
|
* HAPI FHIR JPA Server
|
||||||
@ -113,6 +117,13 @@ public class BaseDstu2Config extends BaseConfig {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "myResourceCountsCache")
|
||||||
|
public SingleItemLoadingCache<Map<String, Long>> resourceCountsCache() {
|
||||||
|
SingleItemLoadingCache<Map<String, Long>> retVal = new SingleItemLoadingCache<>(() -> systemDaoDstu2().getResourceCounts());
|
||||||
|
retVal.setCacheMillis(60 * DateUtils.MILLIS_PER_SECOND);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(autowire = Autowire.BY_TYPE)
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
public IHapiTerminologySvc terminologyService() {
|
public IHapiTerminologySvc terminologyService() {
|
||||||
return new HapiTerminologySvcDstu2();
|
return new HapiTerminologySvcDstu2();
|
||||||
|
@ -14,8 +14,10 @@ import ca.uhn.fhir.jpa.term.HapiTerminologySvcDstu3;
|
|||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvcDstu3;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvcDstu3;
|
||||||
import ca.uhn.fhir.jpa.term.TerminologyLoaderSvcImpl;
|
import ca.uhn.fhir.jpa.term.TerminologyLoaderSvcImpl;
|
||||||
|
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
|
||||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3;
|
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainDstu3;
|
||||||
import ca.uhn.fhir.validation.IValidatorModule;
|
import ca.uhn.fhir.validation.IValidatorModule;
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
import org.hl7.fhir.dstu3.hapi.ctx.IValidationSupport;
|
||||||
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
|
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
|
||||||
import org.hl7.fhir.r4.utils.IResourceValidator;
|
import org.hl7.fhir.r4.utils.IResourceValidator;
|
||||||
@ -26,6 +28,8 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JPA Server
|
* HAPI FHIR JPA Server
|
||||||
@ -35,9 +39,9 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -77,6 +81,14 @@ public class BaseDstu3Config extends BaseConfig {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean(name = "myResourceCountsCache")
|
||||||
|
public SingleItemLoadingCache<Map<String, Long>> resourceCountsCache() {
|
||||||
|
SingleItemLoadingCache<Map<String, Long>> retVal = new SingleItemLoadingCache<>(() -> systemDaoDstu3().getResourceCounts());
|
||||||
|
retVal.setCacheMillis(60 * DateUtils.MILLIS_PER_SECOND);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(autowire = Autowire.BY_TYPE)
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
public IFulltextSearchSvc searchDaoDstu3() {
|
public IFulltextSearchSvc searchDaoDstu3() {
|
||||||
FulltextSearchSvcImpl searchDao = new FulltextSearchSvcImpl();
|
FulltextSearchSvcImpl searchDao = new FulltextSearchSvcImpl();
|
||||||
|
@ -15,8 +15,10 @@ import ca.uhn.fhir.jpa.term.HapiTerminologySvcR4;
|
|||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologyLoaderSvc;
|
||||||
import ca.uhn.fhir.jpa.term.IHapiTerminologySvcR4;
|
import ca.uhn.fhir.jpa.term.IHapiTerminologySvcR4;
|
||||||
import ca.uhn.fhir.jpa.term.TerminologyLoaderSvcImpl;
|
import ca.uhn.fhir.jpa.term.TerminologyLoaderSvcImpl;
|
||||||
|
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
|
||||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
|
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
|
||||||
import ca.uhn.fhir.validation.IValidatorModule;
|
import ca.uhn.fhir.validation.IValidatorModule;
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
|
||||||
import org.hl7.fhir.r4.hapi.rest.server.GraphQLProvider;
|
import org.hl7.fhir.r4.hapi.rest.server.GraphQLProvider;
|
||||||
import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator;
|
import org.hl7.fhir.r4.hapi.validation.FhirInstanceValidator;
|
||||||
@ -29,6 +31,8 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JPA Server
|
* HAPI FHIR JPA Server
|
||||||
@ -38,9 +42,9 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -92,6 +96,13 @@ public class BaseR4Config extends BaseConfig {
|
|||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "myResourceCountsCache")
|
||||||
|
public SingleItemLoadingCache<Map<String, Long>> resourceCountsCache() {
|
||||||
|
SingleItemLoadingCache<Map<String, Long>> retVal = new SingleItemLoadingCache<>(() -> systemDaoR4().getResourceCounts());
|
||||||
|
retVal.setCacheMillis(60 * DateUtils.MILLIS_PER_SECOND);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(autowire = Autowire.BY_TYPE)
|
@Bean(autowire = Autowire.BY_TYPE)
|
||||||
public IFulltextSearchSvc searchDaoR4() {
|
public IFulltextSearchSvc searchDaoR4() {
|
||||||
FulltextSearchSvcImpl searchDao = new FulltextSearchSvcImpl();
|
FulltextSearchSvcImpl searchDao = new FulltextSearchSvcImpl();
|
||||||
|
@ -9,9 +9,9 @@ package ca.uhn.fhir.jpa.dao;
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -31,6 +31,7 @@ import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
|
|||||||
import ca.uhn.fhir.jpa.util.DeleteConflict;
|
import ca.uhn.fhir.jpa.util.DeleteConflict;
|
||||||
import ca.uhn.fhir.jpa.util.ExpungeOptions;
|
import ca.uhn.fhir.jpa.util.ExpungeOptions;
|
||||||
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
|
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
|
||||||
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
import ca.uhn.fhir.model.api.*;
|
import ca.uhn.fhir.model.api.*;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||||
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
|
||||||
@ -79,9 +80,12 @@ import org.springframework.data.domain.Slice;
|
|||||||
import org.springframework.data.domain.SliceImpl;
|
import org.springframework.data.domain.SliceImpl;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
@ -717,14 +721,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
return mySearchParamExtractor.extractSearchParamUri(theEntity, theResource);
|
return mySearchParamExtractor.extractSearchParamUri(theEntity, theResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractTagsHapi(IResource theResource, ResourceTable theEntity, Set<TagDefinition> allDefs) {
|
private void extractTagsHapi(IResource theResource, ResourceTable theEntity, Set<ResourceTag> allDefs) {
|
||||||
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(theResource);
|
TagList tagList = ResourceMetadataKeyEnum.TAG_LIST.get(theResource);
|
||||||
if (tagList != null) {
|
if (tagList != null) {
|
||||||
for (Tag next : tagList) {
|
for (Tag next : tagList) {
|
||||||
TagDefinition tag = getTagOrNull(TagTypeEnum.TAG, next.getScheme(), next.getTerm(), next.getLabel());
|
TagDefinition def = getTagOrNull(TagTypeEnum.TAG, next.getScheme(), next.getTerm(), next.getLabel());
|
||||||
if (tag != null) {
|
if (def != null) {
|
||||||
|
ResourceTag tag = theEntity.addTag(def);
|
||||||
allDefs.add(tag);
|
allDefs.add(tag);
|
||||||
theEntity.addTag(tag);
|
|
||||||
theEntity.setHasTags(true);
|
theEntity.setHasTags(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -733,10 +737,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
List<BaseCodingDt> securityLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(theResource);
|
List<BaseCodingDt> securityLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(theResource);
|
||||||
if (securityLabels != null) {
|
if (securityLabels != null) {
|
||||||
for (BaseCodingDt next : securityLabels) {
|
for (BaseCodingDt next : securityLabels) {
|
||||||
TagDefinition tag = getTagOrNull(TagTypeEnum.SECURITY_LABEL, next.getSystemElement().getValue(), next.getCodeElement().getValue(), next.getDisplayElement().getValue());
|
TagDefinition def = getTagOrNull(TagTypeEnum.SECURITY_LABEL, next.getSystemElement().getValue(), next.getCodeElement().getValue(), next.getDisplayElement().getValue());
|
||||||
if (tag != null) {
|
if (def != null) {
|
||||||
|
ResourceTag tag = theEntity.addTag(def);
|
||||||
allDefs.add(tag);
|
allDefs.add(tag);
|
||||||
theEntity.addTag(tag);
|
|
||||||
theEntity.setHasTags(true);
|
theEntity.setHasTags(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -745,24 +749,24 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
List<IdDt> profiles = ResourceMetadataKeyEnum.PROFILES.get(theResource);
|
List<IdDt> profiles = ResourceMetadataKeyEnum.PROFILES.get(theResource);
|
||||||
if (profiles != null) {
|
if (profiles != null) {
|
||||||
for (IIdType next : profiles) {
|
for (IIdType next : profiles) {
|
||||||
TagDefinition tag = getTagOrNull(TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null);
|
TagDefinition def = getTagOrNull(TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null);
|
||||||
if (tag != null) {
|
if (def != null) {
|
||||||
|
ResourceTag tag = theEntity.addTag(def);
|
||||||
allDefs.add(tag);
|
allDefs.add(tag);
|
||||||
theEntity.addTag(tag);
|
|
||||||
theEntity.setHasTags(true);
|
theEntity.setHasTags(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractTagsRi(IAnyResource theResource, ResourceTable theEntity, Set<TagDefinition> allDefs) {
|
private void extractTagsRi(IAnyResource theResource, ResourceTable theEntity, Set<ResourceTag> theAllTags) {
|
||||||
List<? extends IBaseCoding> tagList = theResource.getMeta().getTag();
|
List<? extends IBaseCoding> tagList = theResource.getMeta().getTag();
|
||||||
if (tagList != null) {
|
if (tagList != null) {
|
||||||
for (IBaseCoding next : tagList) {
|
for (IBaseCoding next : tagList) {
|
||||||
TagDefinition tag = getTagOrNull(TagTypeEnum.TAG, next.getSystem(), next.getCode(), next.getDisplay());
|
TagDefinition def = getTagOrNull(TagTypeEnum.TAG, next.getSystem(), next.getCode(), next.getDisplay());
|
||||||
if (tag != null) {
|
if (def != null) {
|
||||||
allDefs.add(tag);
|
ResourceTag tag = theEntity.addTag(def);
|
||||||
theEntity.addTag(tag);
|
theAllTags.add(tag);
|
||||||
theEntity.setHasTags(true);
|
theEntity.setHasTags(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -771,10 +775,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
List<? extends IBaseCoding> securityLabels = theResource.getMeta().getSecurity();
|
List<? extends IBaseCoding> securityLabels = theResource.getMeta().getSecurity();
|
||||||
if (securityLabels != null) {
|
if (securityLabels != null) {
|
||||||
for (IBaseCoding next : securityLabels) {
|
for (IBaseCoding next : securityLabels) {
|
||||||
TagDefinition tag = getTagOrNull(TagTypeEnum.SECURITY_LABEL, next.getSystem(), next.getCode(), next.getDisplay());
|
TagDefinition def = getTagOrNull(TagTypeEnum.SECURITY_LABEL, next.getSystem(), next.getCode(), next.getDisplay());
|
||||||
if (tag != null) {
|
if (def != null) {
|
||||||
allDefs.add(tag);
|
ResourceTag tag = theEntity.addTag(def);
|
||||||
theEntity.addTag(tag);
|
theAllTags.add(tag);
|
||||||
theEntity.setHasTags(true);
|
theEntity.setHasTags(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -783,10 +787,10 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
List<? extends IPrimitiveType<String>> profiles = theResource.getMeta().getProfile();
|
List<? extends IPrimitiveType<String>> profiles = theResource.getMeta().getProfile();
|
||||||
if (profiles != null) {
|
if (profiles != null) {
|
||||||
for (IPrimitiveType<String> next : profiles) {
|
for (IPrimitiveType<String> next : profiles) {
|
||||||
TagDefinition tag = getTagOrNull(TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null);
|
TagDefinition def = getTagOrNull(TagTypeEnum.PROFILE, NS_JPA_PROFILE, next.getValue(), null);
|
||||||
if (tag != null) {
|
if (def != null) {
|
||||||
allDefs.add(tag);
|
ResourceTag tag = theEntity.addTag(def);
|
||||||
theEntity.addTag(tag);
|
theAllTags.add(tag);
|
||||||
theEntity.setHasTags(true);
|
theEntity.setHasTags(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -876,10 +880,12 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
ourLog.debug("Session flush took {}ms for {} inserts and {} updates", sw.getMillis(), insertionCount, updateCount);
|
ourLog.debug("Session flush took {}ms for {} inserts and {} updates", sw.getMillis(), insertionCount, updateCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<TagDefinition> getAllTagDefinitions(ResourceTable theEntity) {
|
private Set<ResourceTag> getAllTagDefinitions(ResourceTable theEntity) {
|
||||||
HashSet<TagDefinition> retVal = Sets.newHashSet();
|
HashSet<ResourceTag> retVal = Sets.newHashSet();
|
||||||
for (ResourceTag next : theEntity.getTags()) {
|
if (theEntity.isHasTags()) {
|
||||||
retVal.add(next.getTag());
|
for (ResourceTag next : theEntity.getTags()) {
|
||||||
|
retVal.add(next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
@ -1173,7 +1179,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
/**
|
/**
|
||||||
* Returns true if the resource has changed (either the contents or the tags)
|
* Returns true if the resource has changed (either the contents or the tags)
|
||||||
*/
|
*/
|
||||||
protected EncodedResource populateResourceIntoEntity(IBaseResource theResource, ResourceTable theEntity, boolean theUpdateHash) {
|
protected EncodedResource populateResourceIntoEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, boolean theUpdateHash) {
|
||||||
if (theEntity.getResourceType() == null) {
|
if (theEntity.getResourceType() == null) {
|
||||||
theEntity.setResourceType(toResourceName(theResource));
|
theEntity.setResourceType(toResourceName(theResource));
|
||||||
}
|
}
|
||||||
@ -1222,11 +1228,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
theEntity.setHashSha256(hashSha256);
|
theEntity.setHashSha256(hashSha256);
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<TagDefinition> allDefs = new HashSet<>();
|
Set<ResourceTag> allDefs = new HashSet<>();
|
||||||
|
Set<ResourceTag> allTagsOld = getAllTagDefinitions(theEntity);
|
||||||
theEntity.setHasTags(false);
|
|
||||||
|
|
||||||
Set<TagDefinition> allTagsOld = getAllTagDefinitions(theEntity);
|
|
||||||
|
|
||||||
if (theResource instanceof IResource) {
|
if (theResource instanceof IResource) {
|
||||||
extractTagsHapi((IResource) theResource, theEntity, allDefs);
|
extractTagsHapi((IResource) theResource, theEntity, allDefs);
|
||||||
@ -1238,32 +1241,33 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
if (def.isStandardType() == false) {
|
if (def.isStandardType() == false) {
|
||||||
String profile = def.getResourceProfile("");
|
String profile = def.getResourceProfile("");
|
||||||
if (isNotBlank(profile)) {
|
if (isNotBlank(profile)) {
|
||||||
TagDefinition tag = getTagOrNull(TagTypeEnum.PROFILE, NS_JPA_PROFILE, profile, null);
|
TagDefinition profileDef = getTagOrNull(TagTypeEnum.PROFILE, NS_JPA_PROFILE, profile, null);
|
||||||
if (tag != null) {
|
if (def != null) {
|
||||||
|
ResourceTag tag = theEntity.addTag(profileDef);
|
||||||
allDefs.add(tag);
|
allDefs.add(tag);
|
||||||
theEntity.addTag(tag);
|
|
||||||
theEntity.setHasTags(true);
|
theEntity.setHasTags(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<ResourceTag> existingTags = new ArrayList<>();
|
// Don't keep duplicate tags
|
||||||
if (theEntity.isHasTags()) {
|
Set<TagDefinition> allDefsPresent = new HashSet<>();
|
||||||
existingTags.addAll(theEntity.getTags());
|
theEntity.getTags().removeIf(theResourceTag -> !allDefsPresent.add(theResourceTag.getTag()));
|
||||||
}
|
|
||||||
for (ResourceTag next : existingTags) {
|
// Remove any tags that have been removed
|
||||||
TagDefinition nextDef = next.getTag();
|
for (ResourceTag next : allTagsOld) {
|
||||||
if (!allDefs.contains(nextDef)) {
|
if (!allDefs.contains(next)) {
|
||||||
if (shouldDroppedTagBeRemovedOnUpdate(theEntity, next)) {
|
if (shouldDroppedTagBeRemovedOnUpdate(theRequest, next)) {
|
||||||
theEntity.getTags().remove(next);
|
theEntity.getTags().remove(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<TagDefinition> allTagsNew = getAllTagDefinitions(theEntity);
|
Set<ResourceTag> allTagsNew = getAllTagDefinitions(theEntity);
|
||||||
if (!allTagsOld.equals(allTagsNew)) {
|
if (!allTagsOld.equals(allTagsNew)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
theEntity.setHasTags(!allTagsNew.isEmpty());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
theEntity.setHashSha256(null);
|
theEntity.setHashSha256(null);
|
||||||
@ -1486,17 +1490,47 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
* The default implementation removes any profile declarations, but leaves tags and security labels in place. Subclasses may choose to override and change this behaviour.
|
* The default implementation removes any profile declarations, but leaves tags and security labels in place. Subclasses may choose to override and change this behaviour.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* See <a href="http://hl7.org/fhir/2015Sep/resource.html#1.11.3.7">Updates to Tags, Profiles, and Security Labels</a> for a description of the logic that the default behaviour folows.
|
* See <a href="http://hl7.org/fhir/resource.html#tag-updates">Updates to Tags, Profiles, and Security Labels</a> for a description of the logic that the default behaviour folows.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theEntity The entity being updated (Do not modify the entity! Undefined behaviour will occur!)
|
* @param theTag The tag
|
||||||
* @param theTag The tag
|
|
||||||
* @return Returns <code>true</code> if the tag should be removed
|
* @return Returns <code>true</code> if the tag should be removed
|
||||||
*/
|
*/
|
||||||
protected boolean shouldDroppedTagBeRemovedOnUpdate(ResourceTable theEntity, ResourceTag theTag) {
|
protected boolean shouldDroppedTagBeRemovedOnUpdate(RequestDetails theRequest, ResourceTag theTag) {
|
||||||
if (theTag.getTag().getTagType() == TagTypeEnum.PROFILE) {
|
|
||||||
|
Set<TagTypeEnum> metaSnapshotModeTokens = null;
|
||||||
|
|
||||||
|
if (theRequest != null) {
|
||||||
|
List<String> metaSnapshotMode = theRequest.getHeaders(JpaConstants.HEADER_META_SNAPSHOT_MODE);
|
||||||
|
if (metaSnapshotMode != null && !metaSnapshotMode.isEmpty()) {
|
||||||
|
metaSnapshotModeTokens = new HashSet<>();
|
||||||
|
for (String nextHeaderValue : metaSnapshotMode) {
|
||||||
|
StringTokenizer tok = new StringTokenizer(nextHeaderValue, ",");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
switch (trim(tok.nextToken())) {
|
||||||
|
case "TAG":
|
||||||
|
metaSnapshotModeTokens.add(TagTypeEnum.TAG);
|
||||||
|
break;
|
||||||
|
case "PROFILE":
|
||||||
|
metaSnapshotModeTokens.add(TagTypeEnum.PROFILE);
|
||||||
|
break;
|
||||||
|
case "SECURITY_LABEL":
|
||||||
|
metaSnapshotModeTokens.add(TagTypeEnum.SECURITY_LABEL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metaSnapshotModeTokens == null) {
|
||||||
|
metaSnapshotModeTokens = Collections.singleton(TagTypeEnum.PROFILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metaSnapshotModeTokens.contains(theTag.getTag().getTagType())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1514,7 +1548,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <R extends IBaseResource> R toResource(Class<R> theResourceType, BaseHasResource theEntity, boolean theForHistoryOperation) {
|
public <R extends IBaseResource> R toResource(Class<R> theResourceType, BaseHasResource theEntity,
|
||||||
|
boolean theForHistoryOperation) {
|
||||||
|
|
||||||
ResourceHistoryTable history;
|
ResourceHistoryTable history;
|
||||||
if (theEntity instanceof ResourceHistoryTable) {
|
if (theEntity instanceof ResourceHistoryTable) {
|
||||||
@ -1639,7 +1674,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
protected ResourceTable updateEntity(RequestDetails theRequest, final IBaseResource theResource, ResourceTable
|
||||||
|
theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
ourLog.debug("Starting entity update");
|
ourLog.debug("Starting entity update");
|
||||||
|
|
||||||
@ -1732,7 +1768,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
theEntity.setNarrativeTextParsedIntoWords(null);
|
theEntity.setNarrativeTextParsedIntoWords(null);
|
||||||
theEntity.setContentTextParsedIntoWords(null);
|
theEntity.setContentTextParsedIntoWords(null);
|
||||||
theEntity.setHashSha256(null);
|
theEntity.setHashSha256(null);
|
||||||
changed = populateResourceIntoEntity(theResource, theEntity, true);
|
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -1844,7 +1880,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
*/
|
*/
|
||||||
compositeStringUniques = extractCompositeStringUniques(theEntity, stringParams, tokenParams, numberParams, quantityParams, dateParams, uriParams, links);
|
compositeStringUniques = extractCompositeStringUniques(theEntity, stringParams, tokenParams, numberParams, quantityParams, dateParams, uriParams, links);
|
||||||
|
|
||||||
changed = populateResourceIntoEntity(theResource, theEntity, true);
|
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, true);
|
||||||
|
|
||||||
theEntity.setUpdated(theUpdateTime);
|
theEntity.setUpdated(theUpdateTime);
|
||||||
if (theResource instanceof IResource) {
|
if (theResource instanceof IResource) {
|
||||||
@ -1874,7 +1910,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
changed = populateResourceIntoEntity(theResource, theEntity, false);
|
changed = populateResourceIntoEntity(theRequest, theResource, theEntity, false);
|
||||||
|
|
||||||
theEntity.setUpdated(theUpdateTime);
|
theEntity.setUpdated(theUpdateTime);
|
||||||
// theEntity.setLanguage(theResource.getLanguage().getValue());
|
// theEntity.setLanguage(theResource.getLanguage().getValue());
|
||||||
@ -2062,11 +2098,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
return theEntity;
|
return theEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable entity, Date theDeletedTimestampOrNull, Date theUpdateTime) {
|
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable
|
||||||
return updateEntity(theResource, entity, theDeletedTimestampOrNull, true, true, theUpdateTime, false, true);
|
entity, Date theDeletedTimestampOrNull, Date theUpdateTime) {
|
||||||
|
return updateEntity(theRequest, theResource, entity, theDeletedTimestampOrNull, true, true, theUpdateTime, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceTable updateInternal(T theResource, boolean thePerformIndexing, boolean theForceUpdateVersion, RequestDetails theRequestDetails, ResourceTable theEntity, IIdType theResourceId, IBaseResource theOldResource) {
|
public ResourceTable updateInternal(RequestDetails theRequest, T theResource, boolean thePerformIndexing,
|
||||||
|
boolean theForceUpdateVersion, RequestDetails theRequestDetails, ResourceTable theEntity, IIdType
|
||||||
|
theResourceId, IBaseResource theOldResource) {
|
||||||
// Notify interceptors
|
// Notify interceptors
|
||||||
ActionRequestDetails requestDetails = null;
|
ActionRequestDetails requestDetails = null;
|
||||||
if (theRequestDetails != null) {
|
if (theRequestDetails != null) {
|
||||||
@ -2085,7 +2124,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform update
|
// Perform update
|
||||||
ResourceTable savedEntity = updateEntity(theResource, theEntity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing);
|
ResourceTable savedEntity = updateEntity(theRequest, theResource, theEntity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
|
* If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
|
||||||
@ -2271,14 +2310,11 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
* @param theResourceType E.g. <code>Patient
|
* @param theResourceType E.g. <code>Patient
|
||||||
* @param thePartsChoices E.g. <code>[[gender=male], [name=SMITH, name=JOHN]]</code>
|
* @param thePartsChoices E.g. <code>[[gender=male], [name=SMITH, name=JOHN]]</code>
|
||||||
*/
|
*/
|
||||||
public static Set<String> extractCompositeStringUniquesValueChains(String theResourceType, List<List<String>> thePartsChoices) {
|
public static Set<String> extractCompositeStringUniquesValueChains(String
|
||||||
|
theResourceType, List<List<String>> thePartsChoices) {
|
||||||
|
|
||||||
for (List<String> next : thePartsChoices) {
|
for (List<String> next : thePartsChoices) {
|
||||||
for (Iterator<String> iter = next.iterator(); iter.hasNext(); ) {
|
next.removeIf(StringUtils::isBlank);
|
||||||
if (isBlank(iter.next())) {
|
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (next.isEmpty()) {
|
if (next.isEmpty()) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
@ -2288,19 +2324,16 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(thePartsChoices, new Comparator<List<String>>() {
|
thePartsChoices.sort((o1, o2) -> {
|
||||||
@Override
|
String str1 = null;
|
||||||
public int compare(List<String> o1, List<String> o2) {
|
String str2 = null;
|
||||||
String str1 = null;
|
if (o1.size() > 0) {
|
||||||
String str2 = null;
|
str1 = o1.get(0);
|
||||||
if (o1.size() > 0) {
|
|
||||||
str1 = o1.get(0);
|
|
||||||
}
|
|
||||||
if (o2.size() > 0) {
|
|
||||||
str2 = o2.get(0);
|
|
||||||
}
|
|
||||||
return StringUtils.compare(str1, str2);
|
|
||||||
}
|
}
|
||||||
|
if (o2.size() > 0) {
|
||||||
|
str2 = o2.get(0);
|
||||||
|
}
|
||||||
|
return compare(str1, str2);
|
||||||
});
|
});
|
||||||
|
|
||||||
List<String> values = new ArrayList<>();
|
List<String> values = new ArrayList<>();
|
||||||
@ -2309,7 +2342,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
return queryStringsToPopulate;
|
return queryStringsToPopulate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void extractCompositeStringUniquesValueChains(String theResourceType, List<List<String>> thePartsChoices, List<String> theValues, Set<String> theQueryStringsToPopulate) {
|
private static void extractCompositeStringUniquesValueChains(String
|
||||||
|
theResourceType, List<List<String>> thePartsChoices, List<String> theValues, Set<String> theQueryStringsToPopulate) {
|
||||||
if (thePartsChoices.size() > 0) {
|
if (thePartsChoices.size() > 0) {
|
||||||
List<String> nextList = thePartsChoices.get(0);
|
List<String> nextList = thePartsChoices.get(0);
|
||||||
Collections.sort(nextList);
|
Collections.sort(nextList);
|
||||||
@ -2446,14 +2480,15 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static List<BaseCodingDt> toBaseCodingList(List<IBaseCoding> theSecurityLabels) {
|
private static List<BaseCodingDt> toBaseCodingList(List<IBaseCoding> theSecurityLabels) {
|
||||||
ArrayList<BaseCodingDt> retVal = new ArrayList<BaseCodingDt>(theSecurityLabels.size());
|
ArrayList<BaseCodingDt> retVal = new ArrayList<>(theSecurityLabels.size());
|
||||||
for (IBaseCoding next : theSecurityLabels) {
|
for (IBaseCoding next : theSecurityLabels) {
|
||||||
retVal.add((BaseCodingDt) next);
|
retVal.add((BaseCodingDt) next);
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Long translateForcedIdToPid(String theResourceName, String theResourceId, IForcedIdDao theForcedIdDao) {
|
protected static Long translateForcedIdToPid(String theResourceName, String theResourceId, IForcedIdDao
|
||||||
|
theForcedIdDao) {
|
||||||
return translateForcedIdToPids(new IdDt(theResourceName, theResourceId), theForcedIdDao).get(0);
|
return translateForcedIdToPids(new IdDt(theResourceName, theResourceId), theForcedIdDao).get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2482,7 +2517,8 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SearchParameterMap translateMatchUrl(IDao theCallingDao, FhirContext theContext, String theMatchUrl, RuntimeResourceDefinition resourceDef) {
|
public static SearchParameterMap translateMatchUrl(IDao theCallingDao, FhirContext theContext, String
|
||||||
|
theMatchUrl, RuntimeResourceDefinition resourceDef) {
|
||||||
SearchParameterMap paramMap = new SearchParameterMap();
|
SearchParameterMap paramMap = new SearchParameterMap();
|
||||||
List<NameValuePair> parameters = translateMatchUrl(theMatchUrl);
|
List<NameValuePair> parameters = translateMatchUrl(theMatchUrl);
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
|
|||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.IServerOperationInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.method.SearchMethodBinding;
|
import ca.uhn.fhir.rest.server.method.SearchMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.util.*;
|
import ca.uhn.fhir.util.*;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
import org.hl7.fhir.instance.model.api.*;
|
||||||
@ -175,7 +176,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DaoMethodOutcome delete(IIdType theId, List<DeleteConflict> theDeleteConflicts, RequestDetails theRequestDetails) {
|
public DaoMethodOutcome delete(IIdType theId, List<DeleteConflict> theDeleteConflicts, RequestDetails theReques) {
|
||||||
if (theId == null || !theId.hasIdPart()) {
|
if (theId == null || !theId.hasIdPart()) {
|
||||||
throw new InvalidRequestException("Can not perform delete, no ID provided");
|
throw new InvalidRequestException("Can not perform delete, no ID provided");
|
||||||
}
|
}
|
||||||
@ -208,12 +209,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
T resourceToDelete = toResource(myResourceType, entity, false);
|
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||||
|
|
||||||
// Notify IServerOperationInterceptors about pre-action call
|
// Notify IServerOperationInterceptors about pre-action call
|
||||||
if (theRequestDetails != null) {
|
if (theReques != null) {
|
||||||
theRequestDetails.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
|
theReques.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
|
||||||
}
|
}
|
||||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||||
if (next instanceof IServerOperationInterceptor) {
|
if (next instanceof IServerOperationInterceptor) {
|
||||||
((IServerOperationInterceptor) next).resourcePreDelete(theRequestDetails, resourceToDelete);
|
((IServerOperationInterceptor) next).resourcePreDelete(theReques, resourceToDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,23 +223,23 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
preDelete(resourceToDelete, entity);
|
preDelete(resourceToDelete, entity);
|
||||||
|
|
||||||
// Notify interceptors
|
// Notify interceptors
|
||||||
if (theRequestDetails != null) {
|
if (theReques != null) {
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId);
|
ActionRequestDetails requestDetails = new ActionRequestDetails(theReques, getContext(), theId.getResourceType(), theId);
|
||||||
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
Date updateTime = new Date();
|
Date updateTime = new Date();
|
||||||
ResourceTable savedEntity = updateEntity(null, entity, updateTime, updateTime);
|
ResourceTable savedEntity = updateEntity(theReques, null, entity, updateTime, updateTime);
|
||||||
resourceToDelete.setId(entity.getIdDt());
|
resourceToDelete.setId(entity.getIdDt());
|
||||||
|
|
||||||
// Notify JPA interceptors
|
// Notify JPA interceptors
|
||||||
if (theRequestDetails != null) {
|
if (theReques != null) {
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId);
|
ActionRequestDetails requestDetails = new ActionRequestDetails(theReques, getContext(), theId.getResourceType(), theId);
|
||||||
theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete);
|
theReques.getRequestOperationCallback().resourceDeleted(resourceToDelete);
|
||||||
}
|
}
|
||||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||||
if (next instanceof IServerOperationInterceptor) {
|
if (next instanceof IServerOperationInterceptor) {
|
||||||
((IServerOperationInterceptor) next).resourceDeleted(theRequestDetails, resourceToDelete);
|
((IServerOperationInterceptor) next).resourceDeleted(theReques, resourceToDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +273,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
* transaction processors
|
* transaction processors
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public DeleteMethodOutcome deleteByUrl(String theUrl, List<DeleteConflict> deleteConflicts, RequestDetails theRequestDetails) {
|
public DeleteMethodOutcome deleteByUrl(String theUrl, List<DeleteConflict> deleteConflicts, RequestDetails theRequest) {
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
|
|
||||||
Set<Long> resource = processMatchUrl(theUrl, myResourceType);
|
Set<Long> resource = processMatchUrl(theUrl, myResourceType);
|
||||||
@ -290,12 +291,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
T resourceToDelete = toResource(myResourceType, entity, false);
|
T resourceToDelete = toResource(myResourceType, entity, false);
|
||||||
|
|
||||||
// Notify IServerOperationInterceptors about pre-action call
|
// Notify IServerOperationInterceptors about pre-action call
|
||||||
if (theRequestDetails != null) {
|
if (theRequest != null) {
|
||||||
theRequestDetails.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
|
theRequest.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
|
||||||
}
|
}
|
||||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||||
if (next instanceof IServerOperationInterceptor) {
|
if (next instanceof IServerOperationInterceptor) {
|
||||||
((IServerOperationInterceptor) next).resourcePreDelete(theRequestDetails, resourceToDelete);
|
((IServerOperationInterceptor) next).resourcePreDelete(theRequest, resourceToDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,24 +304,24 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
|
|
||||||
// Notify interceptors
|
// Notify interceptors
|
||||||
IdDt idToDelete = entity.getIdDt();
|
IdDt idToDelete = entity.getIdDt();
|
||||||
if (theRequestDetails != null) {
|
if (theRequest != null) {
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete);
|
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, idToDelete.getResourceType(), idToDelete);
|
||||||
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform delete
|
// Perform delete
|
||||||
Date updateTime = new Date();
|
Date updateTime = new Date();
|
||||||
updateEntity(null, entity, updateTime, updateTime);
|
updateEntity(theRequest, null, entity, updateTime, updateTime);
|
||||||
resourceToDelete.setId(entity.getIdDt());
|
resourceToDelete.setId(entity.getIdDt());
|
||||||
|
|
||||||
// Notify JPA interceptors
|
// Notify JPA interceptors
|
||||||
if (theRequestDetails != null) {
|
if (theRequest != null) {
|
||||||
theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete);
|
theRequest.getRequestOperationCallback().resourceDeleted(resourceToDelete);
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete);
|
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, idToDelete.getResourceType(), idToDelete);
|
||||||
}
|
}
|
||||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||||
if (next instanceof IServerOperationInterceptor) {
|
if (next instanceof IServerOperationInterceptor) {
|
||||||
((IServerOperationInterceptor) next).resourceDeleted(theRequestDetails, resourceToDelete);
|
((IServerOperationInterceptor) next).resourceDeleted(theRequest, resourceToDelete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,7 +367,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DaoMethodOutcome doCreate(T theResource, String theIfNoneExist, boolean thePerformIndexing, Date theUpdateTime, RequestDetails theRequestDetails) {
|
private DaoMethodOutcome doCreate(T theResource, String theIfNoneExist, boolean thePerformIndexing, Date theUpdateTime, RequestDetails theRequest) {
|
||||||
StopWatch w = new StopWatch();
|
StopWatch w = new StopWatch();
|
||||||
|
|
||||||
preProcessResourceForStorage(theResource);
|
preProcessResourceForStorage(theResource);
|
||||||
@ -405,23 +406,23 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify interceptors
|
// Notify interceptors
|
||||||
if (theRequestDetails != null) {
|
if (theRequest != null) {
|
||||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theResource);
|
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getContext(), theResource);
|
||||||
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
|
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify JPA interceptors
|
// Notify JPA interceptors
|
||||||
if (theRequestDetails != null) {
|
if (theRequest != null) {
|
||||||
theRequestDetails.getRequestOperationCallback().resourcePreCreate(theResource);
|
theRequest.getRequestOperationCallback().resourcePreCreate(theResource);
|
||||||
}
|
}
|
||||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||||
if (next instanceof IServerOperationInterceptor) {
|
if (next instanceof IServerOperationInterceptor) {
|
||||||
((IServerOperationInterceptor) next).resourcePreCreate(theRequestDetails, theResource);
|
((IServerOperationInterceptor) next).resourcePreCreate(theRequest, theResource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform actual DB update
|
// Perform actual DB update
|
||||||
ResourceTable updatedEntity = updateEntity(theResource, entity, null, thePerformIndexing, thePerformIndexing, theUpdateTime, false, thePerformIndexing);
|
ResourceTable updatedEntity = updateEntity(theRequest, theResource, entity, null, thePerformIndexing, thePerformIndexing, theUpdateTime, false, thePerformIndexing);
|
||||||
theResource.setId(entity.getIdDt());
|
theResource.setId(entity.getIdDt());
|
||||||
|
|
||||||
|
|
||||||
@ -436,12 +437,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
|
|
||||||
// Notify JPA interceptors
|
// Notify JPA interceptors
|
||||||
if (!updatedEntity.isUnchangedInCurrentOperation()) {
|
if (!updatedEntity.isUnchangedInCurrentOperation()) {
|
||||||
if (theRequestDetails != null) {
|
if (theRequest != null) {
|
||||||
theRequestDetails.getRequestOperationCallback().resourceCreated(theResource);
|
theRequest.getRequestOperationCallback().resourceCreated(theResource);
|
||||||
}
|
}
|
||||||
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
for (IServerInterceptor next : getConfig().getInterceptors()) {
|
||||||
if (next instanceof IServerOperationInterceptor) {
|
if (next instanceof IServerOperationInterceptor) {
|
||||||
((IServerOperationInterceptor) next).resourceCreated(theRequestDetails, theResource);
|
((IServerOperationInterceptor) next).resourceCreated(theRequest, theResource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -931,7 +932,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
public void reindex(T theResource, ResourceTable theEntity) {
|
public void reindex(T theResource, ResourceTable theEntity) {
|
||||||
ourLog.debug("Indexing resource {} - PID {}", theResource.getIdElement().getValue(), theEntity.getId());
|
ourLog.debug("Indexing resource {} - PID {}", theResource.getIdElement().getValue(), theEntity.getId());
|
||||||
CURRENTLY_REINDEXING.put(theResource, Boolean.TRUE);
|
CURRENTLY_REINDEXING.put(theResource, Boolean.TRUE);
|
||||||
updateEntity(theResource, theEntity, null, true, false, theEntity.getUpdatedDate(), true, false);
|
updateEntity(null, theResource, theEntity, null, true, false, theEntity.getUpdatedDate(), true, false);
|
||||||
CURRENTLY_REINDEXING.put(theResource, null);
|
CURRENTLY_REINDEXING.put(theResource, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1232,7 +1233,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If we aren't indexing, that means we're doing this inside a transaction.
|
* If we aren't indexing, that means we're doing this inside a transaction.
|
||||||
* The transaction will do the actual storate to the database a bit later on,
|
* The transaction will do the actual storage to the database a bit later on,
|
||||||
* after placeholder IDs have been replaced, by calling {@link #updateInternal}
|
* after placeholder IDs have been replaced, by calling {@link #updateInternal}
|
||||||
* directly. So we just bail now.
|
* directly. So we just bail now.
|
||||||
*/
|
*/
|
||||||
@ -1245,7 +1246,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||||||
/*
|
/*
|
||||||
* Otherwise, we're not in a transaction
|
* Otherwise, we're not in a transaction
|
||||||
*/
|
*/
|
||||||
ResourceTable savedEntity = updateInternal(theResource, thePerformIndexing, theForceUpdateVersion, theRequestDetails, entity, resourceId, oldResource);
|
ResourceTable savedEntity = updateInternal(theRequestDetails, theResource, thePerformIndexing, theForceUpdateVersion, theRequestDetails, entity, resourceId, oldResource);
|
||||||
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, theResource).setCreated(false);
|
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, theResource).setCreated(false);
|
||||||
|
|
||||||
if (!thePerformIndexing) {
|
if (!thePerformIndexing) {
|
||||||
|
@ -8,6 +8,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||||||
import ca.uhn.fhir.jpa.util.ExpungeOptions;
|
import ca.uhn.fhir.jpa.util.ExpungeOptions;
|
||||||
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
|
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
|
||||||
import ca.uhn.fhir.jpa.util.ReindexFailureException;
|
import ca.uhn.fhir.jpa.util.ReindexFailureException;
|
||||||
|
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
@ -15,6 +16,7 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|||||||
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
@ -23,16 +25,10 @@ import org.springframework.transaction.support.TransactionCallback;
|
|||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
import javax.persistence.Tuple;
|
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import java.util.*;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
|
||||||
import javax.persistence.criteria.Root;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
@ -74,6 +70,10 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||||||
private PlatformTransactionManager myTxManager;
|
private PlatformTransactionManager myTxManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IResourceTableDao myResourceTableDao;
|
private IResourceTableDao myResourceTableDao;
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("myResourceCountsCache")
|
||||||
|
public SingleItemLoadingCache<Map<String, Long>> myResourceCountsCache;
|
||||||
|
|
||||||
|
|
||||||
private int doPerformReindexingPass(final Integer theCount) {
|
private int doPerformReindexingPass(final Integer theCount) {
|
||||||
/*
|
/*
|
||||||
@ -165,23 +165,23 @@ public abstract class BaseHapiFhirSystemDao<T, MT> extends BaseHapiFhirDao<IBase
|
|||||||
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
|
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Long> getResourceCounts() {
|
public Map<String, Long> getResourceCounts() {
|
||||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
|
||||||
CriteriaQuery<Tuple> cq = builder.createTupleQuery();
|
|
||||||
Root<?> from = cq.from(ResourceTable.class);
|
|
||||||
cq.multiselect(from.get("myResourceType").as(String.class), builder.count(from.get("myResourceType")).as(Long.class));
|
|
||||||
cq.groupBy(from.get("myResourceType"));
|
|
||||||
|
|
||||||
TypedQuery<Tuple> q = myEntityManager.createQuery(cq);
|
|
||||||
|
|
||||||
Map<String, Long> retVal = new HashMap<>();
|
Map<String, Long> retVal = new HashMap<>();
|
||||||
for (Tuple next : q.getResultList()) {
|
|
||||||
String resourceName = next.get(0, String.class);
|
List<Map<?,?>> counts = myResourceTableDao.getResourceCounts();
|
||||||
Long count = next.get(1, Long.class);
|
for (Map<?, ?> next : counts) {
|
||||||
retVal.put(resourceName, count);
|
retVal.put(next.get("type").toString(), Long.parseLong(next.get("count").toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Map<String, Long> getResourceCountsFromCache() {
|
||||||
|
return myResourceCountsCache.get();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBundleProvider history(Date theSince, Date theUntil, RequestDetails theRequestDetails) {
|
public IBundleProvider history(Date theSince, Date theUntil, RequestDetails theRequestDetails) {
|
||||||
if (theRequestDetails != null) {
|
if (theRequestDetails != null) {
|
||||||
|
@ -27,6 +27,7 @@ import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
|||||||
import ca.uhn.fhir.model.dstu2.resource.Subscription;
|
import ca.uhn.fhir.model.dstu2.resource.Subscription;
|
||||||
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
|
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
@ -39,8 +40,6 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
|
|||||||
|
|
||||||
public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
|
public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subscription> implements IFhirResourceDaoSubscription<Subscription> {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoSubscriptionDstu2.class);
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISubscriptionTableDao mySubscriptionTableDao;
|
private ISubscriptionTableDao mySubscriptionTableDao;
|
||||||
|
|
||||||
@ -74,9 +73,9 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2<Subsc
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
|
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
|
||||||
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||||
|
|
||||||
if (theDeletedTimestampOrNull != null) {
|
if (theDeletedTimestampOrNull != null) {
|
||||||
mySubscriptionTableDao.deleteAllForSubscription(theEntity);
|
mySubscriptionTableDao.deleteAllForSubscription(theEntity);
|
||||||
|
@ -387,9 +387,9 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao<Bundle, MetaDt> {
|
|||||||
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
|
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
|
||||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||||
if (updatedEntities.contains(nextOutcome.getEntity())) {
|
if (updatedEntities.contains(nextOutcome.getEntity())) {
|
||||||
updateInternal(nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
|
updateInternal(theRequestDetails, nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
|
||||||
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
|
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
|
||||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, updateTime, false, true);
|
updateEntity(theRequestDetails, nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, updateTime, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,10 @@ import ca.uhn.fhir.jpa.util.ExpungeOutcome;
|
|||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -41,6 +44,14 @@ public interface IFhirSystemDao<T, MT> extends IDao {
|
|||||||
|
|
||||||
Map<String, Long> getResourceCounts();
|
Map<String, Long> getResourceCounts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Returns a cached count of resources using a cache that regularly
|
||||||
|
* refreshes in the background. This method will never
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
Map<String, Long> getResourceCountsFromCache();
|
||||||
|
|
||||||
|
|
||||||
IBundleProvider history(Date theDate, Date theUntil, RequestDetails theRequestDetails);
|
IBundleProvider history(Date theDate, Date theUntil, RequestDetails theRequestDetails);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,9 @@ import org.springframework.data.jpa.repository.Modifying;
|
|||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* HAPI FHIR JPA Server
|
* HAPI FHIR JPA Server
|
||||||
@ -42,6 +45,9 @@ public interface IResourceTableDao extends JpaRepository<ResourceTable, Long> {
|
|||||||
@Query("SELECT t.myId FROM ResourceTable t WHERE t.myIndexStatus IS NULL")
|
@Query("SELECT t.myId FROM ResourceTable t WHERE t.myIndexStatus IS NULL")
|
||||||
Slice<Long> findUnindexed(Pageable thePageRequest);
|
Slice<Long> findUnindexed(Pageable thePageRequest);
|
||||||
|
|
||||||
|
@Query("SELECT t.myResourceType as type, COUNT(*) as count FROM ResourceTable t GROUP BY t.myResourceType")
|
||||||
|
List<Map<?,?>> getResourceCounts();
|
||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Query("UPDATE ResourceTable r SET r.myIndexStatus = null WHERE r.myResourceType = :restype")
|
@Query("UPDATE ResourceTable r SET r.myIndexStatus = null WHERE r.myResourceType = :restype")
|
||||||
int markResourcesOfTypeAsRequiringReindexing(@Param("restype") String theResourceType);
|
int markResourcesOfTypeAsRequiringReindexing(@Param("restype") String theResourceType);
|
||||||
|
@ -199,9 +199,9 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3<CodeSys
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||||
|
|
||||||
CodeSystem cs = (CodeSystem) theResource;
|
CodeSystem cs = (CodeSystem) theResource;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||||||
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.hl7.fhir.dstu3.model.Subscription;
|
import org.hl7.fhir.dstu3.model.Subscription;
|
||||||
@ -82,9 +83,9 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3<Subsc
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
|
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
|
||||||
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||||
|
|
||||||
if (theDeletedTimestampOrNull != null) {
|
if (theDeletedTimestampOrNull != null) {
|
||||||
mySubscriptionTableDao.deleteAllForSubscription(theEntity);
|
mySubscriptionTableDao.deleteAllForSubscription(theEntity);
|
||||||
|
@ -545,9 +545,9 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||||
|
|
||||||
if (updatedEntities.contains(nextOutcome.getEntity())) {
|
if (updatedEntities.contains(nextOutcome.getEntity())) {
|
||||||
updateInternal(nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
|
updateInternal(theRequestDetails, nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
|
||||||
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
|
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
|
||||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, theUpdateTime, false, true);
|
updateEntity(theRequestDetails, nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, theUpdateTime, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ import org.hl7.fhir.r4.model.Coding;
|
|||||||
import org.hl7.fhir.r4.model.IdType;
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -172,9 +173,9 @@ public class FhirResourceDaoCodeSystemR4 extends FhirResourceDaoR4<CodeSystem> i
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing,
|
||||||
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
boolean theUpdateVersion, Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||||
|
|
||||||
CodeSystem cs = (CodeSystem) theResource;
|
CodeSystem cs = (CodeSystem) theResource;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||||||
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
import ca.uhn.fhir.jpa.entity.SubscriptionTable;
|
||||||
import ca.uhn.fhir.parser.DataFormatException;
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
@ -36,7 +37,6 @@ import org.hl7.fhir.r4.model.Subscription;
|
|||||||
import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType;
|
import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType;
|
||||||
import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus;
|
import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -75,9 +75,9 @@ public class FhirResourceDaoSubscriptionR4 extends FhirResourceDaoR4<Subscriptio
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
|
protected ResourceTable updateEntity(RequestDetails theRequest, IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, boolean theUpdateVersion,
|
||||||
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
Date theUpdateTime, boolean theForceUpdate, boolean theCreateNewHistoryEntry) {
|
||||||
ResourceTable retVal = super.updateEntity(theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
ResourceTable retVal = super.updateEntity(theRequest, theResource, theEntity, theDeletedTimestampOrNull, thePerformIndexing, theUpdateVersion, theUpdateTime, theForceUpdate, theCreateNewHistoryEntry);
|
||||||
|
|
||||||
if (theDeletedTimestampOrNull != null) {
|
if (theDeletedTimestampOrNull != null) {
|
||||||
Long subscriptionId = getSubscriptionTablePidForSubscriptionResource(theEntity.getIdDt());
|
Long subscriptionId = getSubscriptionTablePidForSubscriptionResource(theEntity.getIdDt());
|
||||||
|
@ -51,7 +51,6 @@ import ca.uhn.fhir.util.FhirTerser;
|
|||||||
import ca.uhn.fhir.util.UrlUtil;
|
import ca.uhn.fhir.util.UrlUtil;
|
||||||
import ca.uhn.fhir.util.UrlUtil.UrlParts;
|
import ca.uhn.fhir.util.UrlUtil.UrlParts;
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import javolution.io.Struct;
|
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.http.NameValuePair;
|
import org.apache.http.NameValuePair;
|
||||||
import org.hl7.fhir.instance.model.api.*;
|
import org.hl7.fhir.instance.model.api.*;
|
||||||
@ -317,7 +316,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Map<BundleEntryComponent, ResourceTable> doTransactionWriteOperations(ServletRequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date theUpdateTime, Set<IdType> theAllIds,
|
private Map<BundleEntryComponent, ResourceTable> doTransactionWriteOperations(RequestDetails theRequestDetails, Bundle theRequest, String theActionName, Date theUpdateTime, Set<IdType> theAllIds,
|
||||||
Map<IdType, IdType> theIdSubstitutions, Map<IdType, DaoMethodOutcome> theIdToPersistedOutcome, Bundle theResponse, IdentityHashMap<BundleEntryComponent, Integer> theOriginalRequestOrder, List<BundleEntryComponent> theEntries) {
|
Map<IdType, IdType> theIdSubstitutions, Map<IdType, DaoMethodOutcome> theIdToPersistedOutcome, Bundle theResponse, IdentityHashMap<BundleEntryComponent, Integer> theOriginalRequestOrder, List<BundleEntryComponent> theEntries) {
|
||||||
Set<String> deletedResources = new HashSet<>();
|
Set<String> deletedResources = new HashSet<>();
|
||||||
List<DeleteConflict> deleteConflicts = new ArrayList<>();
|
List<DeleteConflict> deleteConflicts = new ArrayList<>();
|
||||||
@ -545,9 +544,9 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||||||
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
|
||||||
|
|
||||||
if (updatedEntities.contains(nextOutcome.getEntity())) {
|
if (updatedEntities.contains(nextOutcome.getEntity())) {
|
||||||
updateInternal(nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
|
updateInternal(theRequestDetails, nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
|
||||||
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
|
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
|
||||||
updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, theUpdateTime, false, true);
|
updateEntity(theRequestDetails, nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, theUpdateTime, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,7 +712,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void handleTransactionCreateOrUpdateOutcome(Map<IdType, IdType> idSubstitutions, Map<IdType, DaoMethodOutcome> idToPersistedOutcome, IdType nextResourceId, DaoMethodOutcome outcome,
|
private static void handleTransactionCreateOrUpdateOutcome(Map<IdType, IdType> idSubstitutions, Map<IdType, DaoMethodOutcome> idToPersistedOutcome, IdType nextResourceId, DaoMethodOutcome outcome,
|
||||||
BundleEntryComponent newEntry, String theResourceType, IBaseResource theRes, ServletRequestDetails theRequestDetails) {
|
BundleEntryComponent newEntry, String theResourceType, IBaseResource theRes, RequestDetails theRequestDetails) {
|
||||||
IdType newId = (IdType) outcome.getId().toUnqualifiedVersionless();
|
IdType newId = (IdType) outcome.getId().toUnqualifiedVersionless();
|
||||||
IdType resourceId = isPlaceholder(nextResourceId) ? nextResourceId : nextResourceId.toUnqualifiedVersionless();
|
IdType resourceId = isPlaceholder(nextResourceId) ? nextResourceId : nextResourceId.toUnqualifiedVersionless();
|
||||||
if (newId.equals(resourceId) == false) {
|
if (newId.equals(resourceId) == false) {
|
||||||
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
|||||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
import ca.uhn.fhir.jpa.dao.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
|
||||||
|
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
import ca.uhn.fhir.model.dstu2.resource.Bundle;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||||
@ -44,6 +45,8 @@ import ca.uhn.fhir.rest.server.provider.dstu2.ServerConformanceProvider;
|
|||||||
import ca.uhn.fhir.util.CoverageIgnore;
|
import ca.uhn.fhir.util.CoverageIgnore;
|
||||||
import ca.uhn.fhir.util.ExtensionConstants;
|
import ca.uhn.fhir.util.ExtensionConstants;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
|
|
||||||
public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
|
public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
|
||||||
|
|
||||||
private volatile Conformance myCachedValue;
|
private volatile Conformance myCachedValue;
|
||||||
@ -52,16 +55,7 @@ public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
|
|||||||
private boolean myIncludeResourceCounts;
|
private boolean myIncludeResourceCounts;
|
||||||
private RestfulServer myRestfulServer;
|
private RestfulServer myRestfulServer;
|
||||||
private IFhirSystemDao<Bundle, MetaDt> mySystemDao;
|
private IFhirSystemDao<Bundle, MetaDt> mySystemDao;
|
||||||
|
private SingleItemLoadingCache<Map<String, Long>> myResourceCountsCache;
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
@CoverageIgnore
|
|
||||||
public JpaConformanceProviderDstu2(){
|
|
||||||
super();
|
|
||||||
super.setCache(false);
|
|
||||||
setIncludeResourceCounts(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -79,10 +73,11 @@ public class JpaConformanceProviderDstu2 extends ServerConformanceProvider {
|
|||||||
public Conformance getServerConformance(HttpServletRequest theRequest) {
|
public Conformance getServerConformance(HttpServletRequest theRequest) {
|
||||||
Conformance retVal = myCachedValue;
|
Conformance retVal = myCachedValue;
|
||||||
|
|
||||||
Map<String, Long> counts = Collections.emptyMap();
|
Map<String, Long> counts = null;
|
||||||
if (myIncludeResourceCounts) {
|
if (myIncludeResourceCounts) {
|
||||||
counts = mySystemDao.getResourceCounts();
|
counts = mySystemDao.getResourceCountsFromCache();
|
||||||
}
|
}
|
||||||
|
counts = defaultIfNull(counts, Collections.emptyMap());
|
||||||
|
|
||||||
FhirContext ctx = myRestfulServer.getFhirContext();
|
FhirContext ctx = myRestfulServer.getFhirContext();
|
||||||
|
|
||||||
|
@ -25,7 +25,9 @@ import ca.uhn.fhir.jpa.util.JpaConstants;
|
|||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
||||||
|
import ca.uhn.fhir.model.primitive.BooleanDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||||
import ca.uhn.fhir.rest.annotation.*;
|
import ca.uhn.fhir.rest.annotation.*;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
@ -79,35 +81,33 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = org.hl7.fhir.r4.model.IntegerType.class)
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = IntegerDt.class)
|
||||||
})
|
})
|
||||||
public Parameters expunge(
|
public Parameters expunge(
|
||||||
@IdParam IIdType theIdParam,
|
@IdParam IIdType theIdParam,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) org.hl7.fhir.r4.model.IntegerType theLimit,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) IntegerDt theLimit,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) org.hl7.fhir.r4.model.BooleanType theExpungeDeletedResources,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) BooleanDt theExpungeDeletedResources,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) org.hl7.fhir.r4.model.BooleanType theExpungeOldVersions
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) BooleanDt theExpungeOldVersions
|
||||||
) {
|
) {
|
||||||
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(theIdParam, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(theIdParam, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
||||||
return JpaSystemProviderDstu2.toExpungeResponse(retVal);
|
return JpaSystemProviderDstu2.toExpungeResponse(retVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = org.hl7.fhir.r4.model.IntegerType.class)
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = IntegerDt.class)
|
||||||
})
|
})
|
||||||
public Parameters expunge(
|
public Parameters expunge(
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) org.hl7.fhir.r4.model.IntegerType theLimit,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) IntegerDt theLimit,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) org.hl7.fhir.r4.model.BooleanType theExpungeDeletedResources,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) BooleanDt theExpungeDeletedResources,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) org.hl7.fhir.r4.model.BooleanType theExpungeOldVersions
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) BooleanDt theExpungeOldVersions
|
||||||
) {
|
) {
|
||||||
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(null, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(null, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
||||||
return JpaSystemProviderDstu2.toExpungeResponse(retVal);
|
return JpaSystemProviderDstu2.toExpungeResponse(retVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
@Operation(name = OPERATION_NAME_META, idempotent = true, returnParameters = {
|
@Operation(name = OPERATION_NAME_META, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = MetaDt.class)
|
@OperationParam(name = "return", type = MetaDt.class)
|
||||||
})
|
})
|
||||||
//@formatter:on
|
|
||||||
public Parameters meta(RequestDetails theRequestDetails) {
|
public Parameters meta(RequestDetails theRequestDetails) {
|
||||||
Parameters parameters = new Parameters();
|
Parameters parameters = new Parameters();
|
||||||
MetaDt metaGetOperation = getDao().metaGetOperation(MetaDt.class, theRequestDetails);
|
MetaDt metaGetOperation = getDao().metaGetOperation(MetaDt.class, theRequestDetails);
|
||||||
@ -115,11 +115,9 @@ public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResour
|
|||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
@Operation(name = OPERATION_NAME_META, idempotent = true, returnParameters = {
|
@Operation(name = OPERATION_NAME_META, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = MetaDt.class)
|
@OperationParam(name = "return", type = MetaDt.class)
|
||||||
})
|
})
|
||||||
//@formatter:on
|
|
||||||
public Parameters meta(@IdParam IdDt theId, RequestDetails theRequestDetails) {
|
public Parameters meta(@IdParam IdDt theId, RequestDetails theRequestDetails) {
|
||||||
Parameters parameters = new Parameters();
|
Parameters parameters = new Parameters();
|
||||||
MetaDt metaGetOperation = getDao().metaGetOperation(MetaDt.class, theId, theRequestDetails);
|
MetaDt metaGetOperation = getDao().metaGetOperation(MetaDt.class, theId, theRequestDetails);
|
||||||
|
@ -187,8 +187,8 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus<Bundl
|
|||||||
public Parameters getResourceCounts() {
|
public Parameters getResourceCounts() {
|
||||||
Parameters retVal = new Parameters();
|
Parameters retVal = new Parameters();
|
||||||
|
|
||||||
Map<String, Long> counts = mySystemDao.getResourceCounts();
|
Map<String, Long> counts = mySystemDao.getResourceCountsFromCache();
|
||||||
counts = new TreeMap<String, Long>(counts);
|
counts = new TreeMap<>(counts);
|
||||||
for (Entry<String, Long> nextEntry : counts.entrySet()) {
|
for (Entry<String, Long> nextEntry : counts.entrySet()) {
|
||||||
retVal.addParameter().setName(new StringDt(nextEntry.getKey())).setValue(new IntegerDt(nextEntry.getValue().intValue()));
|
retVal.addParameter().setName(new StringDt(nextEntry.getKey())).setValue(new IntegerDt(nextEntry.getValue().intValue()));
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||||||
import ca.uhn.fhir.util.CoverageIgnore;
|
import ca.uhn.fhir.util.CoverageIgnore;
|
||||||
import ca.uhn.fhir.util.ExtensionConstants;
|
import ca.uhn.fhir.util.ExtensionConstants;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
|
|
||||||
public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider {
|
public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.server.ServerCapabilityStatementProvider {
|
||||||
|
|
||||||
private volatile CapabilityStatement myCachedValue;
|
private volatile CapabilityStatement myCachedValue;
|
||||||
@ -70,10 +72,11 @@ public class JpaConformanceProviderDstu3 extends org.hl7.fhir.dstu3.hapi.rest.se
|
|||||||
public CapabilityStatement getServerConformance(HttpServletRequest theRequest) {
|
public CapabilityStatement getServerConformance(HttpServletRequest theRequest) {
|
||||||
CapabilityStatement retVal = myCachedValue;
|
CapabilityStatement retVal = myCachedValue;
|
||||||
|
|
||||||
Map<String, Long> counts = Collections.emptyMap();
|
Map<String, Long> counts = null;
|
||||||
if (myIncludeResourceCounts) {
|
if (myIncludeResourceCounts) {
|
||||||
counts = mySystemDao.getResourceCounts();
|
counts = mySystemDao.getResourceCountsFromCache();
|
||||||
}
|
}
|
||||||
|
counts = defaultIfNull(counts, Collections.emptyMap());
|
||||||
|
|
||||||
retVal = super.getServerConformance(theRequest);
|
retVal = super.getServerConformance(theRequest);
|
||||||
for (CapabilityStatementRestComponent nextRest : retVal.getRest()) {
|
for (CapabilityStatementRestComponent nextRest : retVal.getRest()) {
|
||||||
|
@ -31,9 +31,7 @@ import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import org.hl7.fhir.convertors.VersionConvertor_30_40;
|
import org.hl7.fhir.convertors.VersionConvertor_30_40;
|
||||||
import org.hl7.fhir.dstu3.model.IdType;
|
import org.hl7.fhir.dstu3.model.*;
|
||||||
import org.hl7.fhir.dstu3.model.Meta;
|
|
||||||
import org.hl7.fhir.dstu3.model.Parameters;
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
@ -83,13 +81,13 @@ public class JpaResourceProviderDstu3<T extends IAnyResource> extends BaseJpaRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = org.hl7.fhir.r4.model.IntegerType.class)
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = IntegerType.class)
|
||||||
})
|
})
|
||||||
public Parameters expunge(
|
public Parameters expunge(
|
||||||
@IdParam IIdType theIdParam,
|
@IdParam IIdType theIdParam,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) org.hl7.fhir.r4.model.IntegerType theLimit,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) IntegerType theLimit,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) org.hl7.fhir.r4.model.BooleanType theExpungeDeletedResources,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) BooleanType theExpungeDeletedResources,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) org.hl7.fhir.r4.model.BooleanType theExpungeOldVersions
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) BooleanType theExpungeOldVersions
|
||||||
) {
|
) {
|
||||||
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(theIdParam, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(theIdParam, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
||||||
try {
|
try {
|
||||||
@ -100,12 +98,12 @@ public class JpaResourceProviderDstu3<T extends IAnyResource> extends BaseJpaRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
@Operation(name = JpaConstants.OPERATION_NAME_EXPUNGE, idempotent = false, returnParameters = {
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = org.hl7.fhir.r4.model.IntegerType.class)
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT, type = IntegerType.class)
|
||||||
})
|
})
|
||||||
public Parameters expunge(
|
public Parameters expunge(
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) org.hl7.fhir.r4.model.IntegerType theLimit,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) IntegerType theLimit,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) org.hl7.fhir.r4.model.BooleanType theExpungeDeletedResources,
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) BooleanType theExpungeDeletedResources,
|
||||||
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) org.hl7.fhir.r4.model.BooleanType theExpungeOldVersions
|
@OperationParam(name = JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) BooleanType theExpungeOldVersions
|
||||||
) {
|
) {
|
||||||
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(null, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
org.hl7.fhir.r4.model.Parameters retVal = super.doExpunge(null, theLimit, theExpungeDeletedResources, theExpungeOldVersions, null);
|
||||||
try {
|
try {
|
||||||
@ -139,11 +137,9 @@ public class JpaResourceProviderDstu3<T extends IAnyResource> extends BaseJpaRes
|
|||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
@Operation(name = OPERATION_NAME_META_ADD, idempotent = true, returnParameters = {
|
@Operation(name = OPERATION_NAME_META_ADD, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = Meta.class)
|
@OperationParam(name = "return", type = Meta.class)
|
||||||
})
|
})
|
||||||
//@formatter:on
|
|
||||||
public Parameters metaAdd(@IdParam IdType theId, @OperationParam(name = "meta") Meta theMeta, RequestDetails theRequestDetails) {
|
public Parameters metaAdd(@IdParam IdType theId, @OperationParam(name = "meta") Meta theMeta, RequestDetails theRequestDetails) {
|
||||||
if (theMeta == null) {
|
if (theMeta == null) {
|
||||||
throw new InvalidRequestException("Input contains no parameter with name 'meta'");
|
throw new InvalidRequestException("Input contains no parameter with name 'meta'");
|
||||||
@ -154,11 +150,9 @@ public class JpaResourceProviderDstu3<T extends IAnyResource> extends BaseJpaRes
|
|||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
@Operation(name = OPERATION_NAME_META_DELETE, idempotent = true, returnParameters = {
|
@Operation(name = OPERATION_NAME_META_DELETE, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = Meta.class)
|
@OperationParam(name = "return", type = Meta.class)
|
||||||
})
|
})
|
||||||
//@formatter:on
|
|
||||||
public Parameters metaDelete(@IdParam IdType theId, @OperationParam(name = "meta") Meta theMeta, RequestDetails theRequestDetails) {
|
public Parameters metaDelete(@IdParam IdType theId, @OperationParam(name = "meta") Meta theMeta, RequestDetails theRequestDetails) {
|
||||||
if (theMeta == null) {
|
if (theMeta == null) {
|
||||||
throw new InvalidRequestException("Input contains no parameter with name 'meta'");
|
throw new InvalidRequestException("Input contains no parameter with name 'meta'");
|
||||||
|
@ -191,8 +191,8 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundl
|
|||||||
public Parameters getResourceCounts() {
|
public Parameters getResourceCounts() {
|
||||||
Parameters retVal = new Parameters();
|
Parameters retVal = new Parameters();
|
||||||
|
|
||||||
Map<String, Long> counts = mySystemDao.getResourceCounts();
|
Map<String, Long> counts = mySystemDao.getResourceCountsFromCache();
|
||||||
counts = new TreeMap<String, Long>(counts);
|
counts = new TreeMap<>(counts);
|
||||||
for (Entry<String, Long> nextEntry : counts.entrySet()) {
|
for (Entry<String, Long> nextEntry : counts.entrySet()) {
|
||||||
retVal.addParameter().setName((nextEntry.getKey())).setValue(new IntegerType(nextEntry.getValue().intValue()));
|
retVal.addParameter().setName((nextEntry.getKey())).setValue(new IntegerType(nextEntry.getValue().intValue()));
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
|||||||
import ca.uhn.fhir.util.CoverageIgnore;
|
import ca.uhn.fhir.util.CoverageIgnore;
|
||||||
import ca.uhn.fhir.util.ExtensionConstants;
|
import ca.uhn.fhir.util.ExtensionConstants;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
|
|
||||||
public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.ServerCapabilityStatementProvider {
|
public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.ServerCapabilityStatementProvider {
|
||||||
|
|
||||||
private volatile CapabilityStatement myCachedValue;
|
private volatile CapabilityStatement myCachedValue;
|
||||||
@ -70,10 +72,11 @@ public class JpaConformanceProviderR4 extends org.hl7.fhir.r4.hapi.rest.server.S
|
|||||||
public CapabilityStatement getServerConformance(HttpServletRequest theRequest) {
|
public CapabilityStatement getServerConformance(HttpServletRequest theRequest) {
|
||||||
CapabilityStatement retVal = myCachedValue;
|
CapabilityStatement retVal = myCachedValue;
|
||||||
|
|
||||||
Map<String, Long> counts = Collections.emptyMap();
|
Map<String, Long> counts = null;
|
||||||
if (myIncludeResourceCounts) {
|
if (myIncludeResourceCounts) {
|
||||||
counts = mySystemDao.getResourceCounts();
|
counts = mySystemDao.getResourceCountsFromCache();
|
||||||
}
|
}
|
||||||
|
counts = defaultIfNull(counts, Collections.emptyMap());
|
||||||
|
|
||||||
retVal = super.getServerConformance(theRequest);
|
retVal = super.getServerConformance(theRequest);
|
||||||
for (CapabilityStatementRestComponent nextRest : retVal.getRest()) {
|
for (CapabilityStatementRestComponent nextRest : retVal.getRest()) {
|
||||||
|
@ -177,8 +177,8 @@ public class JpaSystemProviderR4 extends BaseJpaSystemProviderDstu2Plus<Bundle,
|
|||||||
public Parameters getResourceCounts() {
|
public Parameters getResourceCounts() {
|
||||||
Parameters retVal = new Parameters();
|
Parameters retVal = new Parameters();
|
||||||
|
|
||||||
Map<String, Long> counts = mySystemDao.getResourceCounts();
|
Map<String, Long> counts = mySystemDao.getResourceCountsFromCache();
|
||||||
counts = new TreeMap<String, Long>(counts);
|
counts = new TreeMap<>(counts);
|
||||||
for (Entry<String, Long> nextEntry : counts.entrySet()) {
|
for (Entry<String, Long> nextEntry : counts.entrySet()) {
|
||||||
retVal.addParameter().setName((nextEntry.getKey())).setValue(new IntegerType(nextEntry.getValue().intValue()));
|
retVal.addParameter().setName((nextEntry.getKey())).setValue(new IntegerType(nextEntry.getValue().intValue()));
|
||||||
}
|
}
|
||||||
|
@ -92,4 +92,11 @@ public class JpaConstants {
|
|||||||
* Output parameter name for the $expunge operation
|
* Output parameter name for the $expunge operation
|
||||||
*/
|
*/
|
||||||
public static final String OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT = "count";
|
public static final String OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT = "count";
|
||||||
|
/**
|
||||||
|
* Header name for the "X-Meta-Snapshot-Mode" header, which
|
||||||
|
* specifies that properties in meta (tags, profiles, security labels)
|
||||||
|
* should be treated as a snapshot, meaning that these things will
|
||||||
|
* be removed if they are nt explicitly included in updates
|
||||||
|
*/
|
||||||
|
public static final String HEADER_META_SNAPSHOT_MODE = "X-Meta-Snapshot-Mode";
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
package ca.uhn.fhir.jpa.util;
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* Smile CDR - CDR
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2016 - 2018 Simpatico Intelligent Systems Inc
|
||||||
|
* %%
|
||||||
|
* All rights reserved.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a simple cache for CapabilityStatement resources to
|
||||||
|
* be returned as server metadata.
|
||||||
|
*/
|
||||||
|
public class SingleItemLoadingCache<T> {
|
||||||
|
private static final Logger ourLog = LoggerFactory.getLogger(SingleItemLoadingCache.class);
|
||||||
|
private static Long ourNowForUnitTest;
|
||||||
|
private final Callable<T> myFetcher;
|
||||||
|
private volatile long myCacheMillis;
|
||||||
|
private AtomicReference<T> myCapabilityStatement = new AtomicReference<>();
|
||||||
|
private long myLastFetched;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public SingleItemLoadingCache(Callable<T> theFetcher) {
|
||||||
|
myFetcher = theFetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void clear() {
|
||||||
|
ourLog.info("Clearning cache");
|
||||||
|
myCapabilityStatement.set(null);
|
||||||
|
myLastFetched = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized T get() {
|
||||||
|
return myCapabilityStatement.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private T refresh() {
|
||||||
|
T retVal;
|
||||||
|
try {
|
||||||
|
retVal = myFetcher.call();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InternalErrorException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
myCapabilityStatement.set(retVal);
|
||||||
|
myLastFetched = now();
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCacheMillis(long theCacheMillis) {
|
||||||
|
myCacheMillis = theCacheMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedDelay = 60000)
|
||||||
|
public void update() {
|
||||||
|
if (myCacheMillis > 0) {
|
||||||
|
long now = now();
|
||||||
|
long expiry = now - myCacheMillis;
|
||||||
|
if (myLastFetched < expiry) {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long now() {
|
||||||
|
if (ourNowForUnitTest != null) {
|
||||||
|
return ourNowForUnitTest;
|
||||||
|
}
|
||||||
|
return System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static void setNowForUnitTest(Long theNowForUnitTest) {
|
||||||
|
ourNowForUnitTest = theNowForUnitTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
|
|
||||||
package ca.uhn.fhir.jpa.util;
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* #%L
|
|
||||||
* HAPI FHIR JPA Server
|
|
||||||
* %%
|
|
||||||
* Copyright (C) 2014 - 2018 University Health Network
|
|
||||||
* %%
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* #L%
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.springframework.aop.framework.Advised;
|
|
||||||
import org.springframework.aop.support.AopUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility to get the Spring proxy object's target object
|
|
||||||
*/
|
|
||||||
public class SpringObjectCaster {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the Spring proxy object's target object
|
|
||||||
* @param proxy
|
|
||||||
* @param clazz
|
|
||||||
* @param <T>
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public static <T> T getTargetObject(Object proxy, Class<T> clazz) throws Exception {
|
|
||||||
while( (AopUtils.isJdkDynamicProxy(proxy))) {
|
|
||||||
return clazz.cast(getTargetObject(((Advised)proxy).getTargetSource().getTarget(), clazz));
|
|
||||||
}
|
|
||||||
|
|
||||||
return clazz.cast(proxy);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,149 @@
|
|||||||
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.jpa.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class FhirResourceDaoR4UpdateTagSnapshotTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithDuplicateTagsWithHeader() {
|
||||||
|
when(mySrd.getHeaders(eq(JpaConstants.HEADER_META_SNAPSHOT_MODE))).thenReturn(Lists.newArrayList("TAG"));
|
||||||
|
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar2", "baz");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar2", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
|
assertEquals(2, p.getMeta().getTag().size());
|
||||||
|
|
||||||
|
p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
|
// It would be nice if this didn't trigger a version update but
|
||||||
|
// i guess it's not so bad that it does
|
||||||
|
assertEquals("2", p.getIdElement().getVersionIdPart());
|
||||||
|
assertEquals(true, p.getActive());
|
||||||
|
assertEquals(1, p.getMeta().getTag().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithFewerTagsNoHeader() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar2", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
|
assertEquals("1", p.getIdElement().getVersionIdPart());
|
||||||
|
assertEquals(true, p.getActive());
|
||||||
|
assertEquals(2, p.getMeta().getTag().size());
|
||||||
|
assertEquals("urn:foo", p.getMeta().getTag().get(0).getSystem());
|
||||||
|
assertThat(p.getMeta().getTag().get(0).getCode(), Matchers.anyOf(Matchers.equalTo("bar"), Matchers.equalTo("bar2")));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithFewerTagsWithHeader() {
|
||||||
|
when(mySrd.getHeaders(eq(JpaConstants.HEADER_META_SNAPSHOT_MODE))).thenReturn(Lists.newArrayList("TAG"));
|
||||||
|
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar2", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
|
// It would be nice if this didn't trigger a version update but
|
||||||
|
// i guess it's not so bad that it does
|
||||||
|
assertEquals("2", p.getIdElement().getVersionIdPart());
|
||||||
|
assertEquals(true, p.getActive());
|
||||||
|
assertEquals(1, p.getMeta().getTag().size());
|
||||||
|
assertEquals("urn:foo", p.getMeta().getTag().get(0).getSystem());
|
||||||
|
assertEquals("bar", p.getMeta().getTag().get(0).getCode());
|
||||||
|
assertEquals("baz", p.getMeta().getTag().get(0).getDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithNoTagsNoHeader() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
|
assertEquals("1", p.getIdElement().getVersionIdPart());
|
||||||
|
assertEquals(true, p.getActive());
|
||||||
|
assertEquals(1, p.getMeta().getTag().size());
|
||||||
|
assertEquals("urn:foo", p.getMeta().getTag().get(0).getSystem());
|
||||||
|
assertEquals("bar", p.getMeta().getTag().get(0).getCode());
|
||||||
|
assertEquals("baz", p.getMeta().getTag().get(0).getDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithNoTagsWithHeader() {
|
||||||
|
when(mySrd.getHeaders(eq(JpaConstants.HEADER_META_SNAPSHOT_MODE))).thenReturn(Lists.newArrayList("TAG"));
|
||||||
|
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.getMeta().addTag("urn:foo", "bar", "baz");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = new Patient();
|
||||||
|
p.setId("A");
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.update(p, mySrd);
|
||||||
|
|
||||||
|
p = myPatientDao.read(new IdType("A"), mySrd);
|
||||||
|
assertEquals(true, p.getActive());
|
||||||
|
assertEquals(0, p.getMeta().getTag().size());
|
||||||
|
// It would be nice if this didn't trigger a version update but
|
||||||
|
// i guess it's not so bad that it does
|
||||||
|
assertEquals("2", p.getIdElement().getVersionIdPart());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -37,6 +37,7 @@ import java.math.BigDecimal;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
@ -169,6 +170,24 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceCounts() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setActive(true);
|
||||||
|
myPatientDao.create(p);
|
||||||
|
|
||||||
|
Observation o = new Observation();
|
||||||
|
o.setStatus(ObservationStatus.AMENDED);
|
||||||
|
myObservationDao.create(o);
|
||||||
|
|
||||||
|
Map<String, Long> counts = mySystemDao.getResourceCounts();
|
||||||
|
assertEquals(new Long(1L), counts.get("Patient"));
|
||||||
|
assertEquals(new Long(1L), counts.get("Observation"));
|
||||||
|
assertEquals(null, counts.get("Organization"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBatchCreateWithBadRead() {
|
public void testBatchCreateWithBadRead() {
|
||||||
Bundle request = new Bundle();
|
Bundle request = new Bundle();
|
||||||
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.jpa.dao.r4.SearchParamRegistryR4;
|
|||||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||||
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
|
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
|
||||||
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
|
import ca.uhn.fhir.jpa.subscription.resthook.SubscriptionRestHookInterceptor;
|
||||||
|
import ca.uhn.fhir.jpa.util.SingleItemLoadingCache;
|
||||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
|
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4;
|
||||||
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
|
||||||
import ca.uhn.fhir.parser.StrictErrorHandler;
|
import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||||
@ -40,6 +41,7 @@ import org.springframework.web.servlet.DispatcherServlet;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
@ -61,6 +63,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||||||
private TerminologyUploaderProviderR4 myTerminologyUploaderProvider;
|
private TerminologyUploaderProviderR4 myTerminologyUploaderProvider;
|
||||||
private Object ourGraphQLProvider;
|
private Object ourGraphQLProvider;
|
||||||
private boolean ourRestHookSubscriptionInterceptorRequested;
|
private boolean ourRestHookSubscriptionInterceptorRequested;
|
||||||
|
protected SingleItemLoadingCache<Map<String, Long>> ourResourceCountsCache;
|
||||||
|
|
||||||
public BaseResourceProviderR4Test() {
|
public BaseResourceProviderR4Test() {
|
||||||
super();
|
super();
|
||||||
@ -99,6 +102,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
|
|||||||
ourRestServer.setServerConformanceProvider(confProvider);
|
ourRestServer.setServerConformanceProvider(confProvider);
|
||||||
|
|
||||||
ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class);
|
ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class);
|
||||||
|
ourResourceCountsCache = (SingleItemLoadingCache<Map<String, Long>>) myAppCtx.getBean("myResourceCountsCache");
|
||||||
|
|
||||||
Server server = new Server(ourPort);
|
Server server = new Server(ourPort);
|
||||||
|
|
||||||
|
@ -1,30 +1,31 @@
|
|||||||
package ca.uhn.fhir.jpa.provider.r4;
|
package ca.uhn.fhir.jpa.provider.r4;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import static org.junit.Assert.fail;
|
import ca.uhn.fhir.util.ExtensionConstants;
|
||||||
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.hl7.fhir.r4.model.CapabilityStatement;
|
import org.hl7.fhir.r4.model.CapabilityStatement;
|
||||||
import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
|
import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
|
||||||
import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
|
import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
|
||||||
|
import org.hl7.fhir.r4.model.Extension;
|
||||||
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class ServerR4Test extends BaseResourceProviderR4Test {
|
public class ServerR4Test extends BaseResourceProviderR4Test {
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerR4Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ServerR4Test.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See #519
|
* See #519
|
||||||
*/
|
*/
|
||||||
@ -35,12 +36,12 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||||||
try {
|
try {
|
||||||
ourLog.info(resp.toString());
|
ourLog.info(resp.toString());
|
||||||
assertEquals(200, resp.getStatusLine().getStatusCode());
|
assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
|
||||||
ourLog.info(respString);
|
ourLog.info(respString);
|
||||||
|
|
||||||
CapabilityStatement cs = myFhirCtx.newXmlParser().parseResource(CapabilityStatement.class, respString);
|
CapabilityStatement cs = myFhirCtx.newXmlParser().parseResource(CapabilityStatement.class, respString);
|
||||||
|
|
||||||
for (CapabilityStatementRestResourceComponent nextResource : cs.getRest().get(0).getResource()) {
|
for (CapabilityStatementRestResourceComponent nextResource : cs.getRest().get(0).getResource()) {
|
||||||
ourLog.info("Testing resource: " + nextResource.getType());
|
ourLog.info("Testing resource: " + nextResource.getType());
|
||||||
Set<String> sps = new HashSet<String>();
|
Set<String> sps = new HashSet<String>();
|
||||||
@ -49,17 +50,70 @@ public class ServerR4Test extends BaseResourceProviderR4Test {
|
|||||||
fail("Duplicate search parameter " + nextSp.getName() + " for resource " + nextResource.getType());
|
fail("Duplicate search parameter " + nextSp.getName() + " for resource " + nextResource.getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sps.contains("_id")) {
|
if (!sps.contains("_id")) {
|
||||||
fail("No search parameter _id for resource " + nextResource.getType());
|
fail("No search parameter _id for resource " + nextResource.getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
IOUtils.closeQuietly(resp.getEntity().getContent());
|
IOUtils.closeQuietly(resp.getEntity().getContent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetadataIncludesResourceCounts() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setActive(true);
|
||||||
|
myClient.create().resource(p).execute();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initial fetch after a clear should return
|
||||||
|
* no results
|
||||||
|
*/
|
||||||
|
ourResourceCountsCache.clear();
|
||||||
|
|
||||||
|
CapabilityStatement capabilityStatement = myClient
|
||||||
|
.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)
|
||||||
|
*/
|
||||||
|
ourResourceCountsCache.update();
|
||||||
|
|
||||||
|
capabilityStatement = myClient
|
||||||
|
.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
|
@AfterClass
|
||||||
public static void afterClassClearContext() {
|
public static void afterClassClearContext() {
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package ca.uhn.fhir.jpa.util;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.CapabilityStatement;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class SingleItemLoadingCacheTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Callable<CapabilityStatement> myFetcher;
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void after() {
|
||||||
|
SingleItemLoadingCache.setNowForUnitTest(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void before() throws Exception {
|
||||||
|
AtomicInteger id = new AtomicInteger();
|
||||||
|
when(myFetcher.call()).thenAnswer(t->{
|
||||||
|
CapabilityStatement retVal = new CapabilityStatement();
|
||||||
|
retVal.setId("" + id.incrementAndGet());
|
||||||
|
return retVal;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCache() {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
SingleItemLoadingCache.setNowForUnitTest(start);
|
||||||
|
|
||||||
|
// Cache is initialized on startup
|
||||||
|
SingleItemLoadingCache<CapabilityStatement> cache = new SingleItemLoadingCache<>(myFetcher);
|
||||||
|
cache.setCacheMillis(500);
|
||||||
|
assertEquals(null, cache.get());
|
||||||
|
|
||||||
|
// Not time to update yet
|
||||||
|
cache.update();
|
||||||
|
assertEquals("1", cache.get().getId());
|
||||||
|
|
||||||
|
// Wait a bit, still not time to update
|
||||||
|
SingleItemLoadingCache.setNowForUnitTest(start + 400);
|
||||||
|
cache.update();
|
||||||
|
assertEquals("1", cache.get().getId());
|
||||||
|
|
||||||
|
// Wait a bit more and the cache is expired
|
||||||
|
SingleItemLoadingCache.setNowForUnitTest(start + 800);
|
||||||
|
cache.update();
|
||||||
|
assertEquals("2", cache.get().getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -257,7 +257,11 @@ public abstract class BaseResource extends BaseElement implements IResource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBaseMetaType setLastUpdated(Date theHeaderDateValue) {
|
public IBaseMetaType setLastUpdated(Date theHeaderDateValue) {
|
||||||
ResourceMetadataKeyEnum.UPDATED.put(BaseResource.this, new InstantDt(theHeaderDateValue));
|
if (theHeaderDateValue == null) {
|
||||||
|
getResourceMetadata().remove(ResourceMetadataKeyEnum.UPDATED);
|
||||||
|
} else {
|
||||||
|
ResourceMetadataKeyEnum.UPDATED.put(BaseResource.this, new InstantDt(theHeaderDateValue));
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,14 +669,15 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||||||
* Creates a new instance of this ID which is identical, but refers to the
|
* Creates a new instance of this ID which is identical, but refers to the
|
||||||
* specific version of this resource ID noted by theVersion.
|
* specific version of this resource ID noted by theVersion.
|
||||||
*
|
*
|
||||||
* @param theVersion
|
* @param theVersion The actual version string, e.g. "1". If theVersion is blank or null, returns the same as {@link #toVersionless()}}
|
||||||
* The actual version string, e.g. "1"
|
|
||||||
* @return A new instance of IdType which is identical, but refers to the
|
* @return A new instance of IdType which is identical, but refers to the
|
||||||
* specific version of this resource ID noted by theVersion.
|
* specific version of this resource ID noted by theVersion.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IdType withVersion(String theVersion) {
|
public IdType withVersion(String theVersion) {
|
||||||
Validate.notBlank(theVersion, "Version may not be null or empty");
|
if (isBlank(theVersion)) {
|
||||||
|
return toVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
if (isLocal() || isUrn()) {
|
if (isLocal() || isUrn()) {
|
||||||
return new IdType(getValueAsString());
|
return new IdType(getValueAsString());
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
package ca.uhn.fhir.model;
|
package ca.uhn.fhir.model;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import static org.junit.Assert.assertFalse;
|
import ca.uhn.fhir.util.TestUtil;
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import org.hl7.fhir.dstu3.model.IdType;
|
import org.hl7.fhir.dstu3.model.IdType;
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
import org.hl7.fhir.dstu3.model.Reference;
|
import org.hl7.fhir.dstu3.model.Reference;
|
||||||
@ -14,82 +9,19 @@ import org.junit.AfterClass;
|
|||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import java.math.BigDecimal;
|
||||||
import ca.uhn.fhir.util.TestUtil;
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class IdTypeDstu3Test {
|
public class IdTypeDstu3Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdTypeDstu3Test.class);
|
||||||
private static FhirContext ourCtx;
|
private static FhirContext ourCtx;
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdTypeDstu3Test.class);
|
private Patient parseAndEncode(Patient patient) {
|
||||||
|
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
@AfterClass
|
ourLog.info("\n" + encoded);
|
||||||
public static void afterClassClearContext() {
|
return ourCtx.newXmlParser().parseResource(Patient.class, encoded);
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUuid() {
|
|
||||||
IdType id = new IdType("urn:uuid:1234-5678");
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.getValueAsString());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.getIdPart());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOid() {
|
|
||||||
IdType id = new IdType("urn:oid:1.2.3.4");
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.getIdPart());
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLocal() {
|
|
||||||
IdType id = new IdType("#foo");
|
|
||||||
assertEquals("#foo", id.getValueAsString());
|
|
||||||
assertEquals("#foo", id.getIdPart());
|
|
||||||
assertEquals("#foo", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("#foo", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
|
|
||||||
assertEquals("#foo", id.withResourceType("Patient").getValue());
|
|
||||||
assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
|
|
||||||
assertEquals("#foo", id.withVersion("2").getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNormal() {
|
|
||||||
IdType id = new IdType("foo");
|
|
||||||
assertEquals("foo", id.getValueAsString());
|
|
||||||
assertEquals("foo", id.getIdPart());
|
|
||||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
|
|
||||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
|
||||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
|
||||||
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -124,14 +56,52 @@ public class IdTypeDstu3Test {
|
|||||||
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBigDecimalIds() {
|
||||||
|
|
||||||
|
IdType id = new IdType(new BigDecimal("123"));
|
||||||
|
assertEquals(id.getIdPartAsBigDecimal(), new BigDecimal("123"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #67
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testComplicatedLocal() {
|
||||||
|
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
|
||||||
|
assertTrue(id.isLocal());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
assertNull(id.getResourceType());
|
||||||
|
assertNull(id.getVersionIdPart());
|
||||||
|
assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
|
||||||
|
|
||||||
|
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
|
||||||
|
assertEquals(id, id2);
|
||||||
|
|
||||||
|
id2 = id2.toUnqualified();
|
||||||
|
assertTrue(id2.isLocal());
|
||||||
|
assertNull(id2.getBaseUrl());
|
||||||
|
assertNull(id2.getResourceType());
|
||||||
|
assertNull(id2.getVersionIdPart());
|
||||||
|
assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConstructorsWithNullArguments() {
|
||||||
|
IdType id = new IdType(null, null, null);
|
||||||
|
assertEquals(null, id.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetectLocal() {
|
public void testDetectLocal() {
|
||||||
IdType id;
|
IdType id;
|
||||||
|
|
||||||
id = new IdType("#123");
|
id = new IdType("#123");
|
||||||
assertEquals("#123", id.getValue());
|
assertEquals("#123", id.getValue());
|
||||||
assertTrue(id.isLocal());
|
assertTrue(id.isLocal());
|
||||||
|
|
||||||
id = new IdType("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1");
|
id = new IdType("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1");
|
||||||
assertEquals("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1", id.getValue());
|
assertEquals("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1", id.getValue());
|
||||||
assertTrue(id.isLocal());
|
assertTrue(id.isLocal());
|
||||||
@ -140,12 +110,6 @@ public class IdTypeDstu3Test {
|
|||||||
assertEquals("http://example.com/Patient/33#123", id.getValue());
|
assertEquals("http://example.com/Patient/33#123", id.getValue());
|
||||||
assertFalse(id.isLocal());
|
assertFalse(id.isLocal());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConstructorsWithNullArguments() {
|
|
||||||
IdType id = new IdType(null, null, null);
|
|
||||||
assertEquals(null, id.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetectLocalBase() {
|
public void testDetectLocalBase() {
|
||||||
@ -161,32 +125,7 @@ public class IdTypeDstu3Test {
|
|||||||
assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
|
assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
|
||||||
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
|
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See #67
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testComplicatedLocal() {
|
|
||||||
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
|
|
||||||
assertTrue(id.isLocal());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
assertNull(id.getResourceType());
|
|
||||||
assertNull(id.getVersionIdPart());
|
|
||||||
assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
|
|
||||||
|
|
||||||
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
|
|
||||||
assertEquals(id, id2);
|
|
||||||
|
|
||||||
id2 = id2.toUnqualified();
|
|
||||||
assertTrue(id2.isLocal());
|
|
||||||
assertNull(id2.getBaseUrl());
|
|
||||||
assertNull(id2.getResourceType());
|
|
||||||
assertNull(id2.getVersionIdPart());
|
|
||||||
assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetermineBase() {
|
public void testDetermineBase() {
|
||||||
|
|
||||||
@ -197,12 +136,60 @@ public class IdTypeDstu3Test {
|
|||||||
|
|
||||||
rr = new IdType("http://foo/fhir/Organization/123/_history/123");
|
rr = new IdType("http://foo/fhir/Organization/123/_history/123");
|
||||||
assertEquals("http://foo/fhir", rr.getBaseUrl());
|
assertEquals("http://foo/fhir", rr.getBaseUrl());
|
||||||
|
|
||||||
rr = new IdType("Organization/123/_history/123");
|
rr = new IdType("Organization/123/_history/123");
|
||||||
assertEquals(null, rr.getBaseUrl());
|
assertEquals(null, rr.getBaseUrl());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLocal() {
|
||||||
|
IdType id = new IdType("#foo");
|
||||||
|
assertEquals("#foo", id.getValueAsString());
|
||||||
|
assertEquals("#foo", id.getIdPart());
|
||||||
|
assertEquals("#foo", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("#foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("#foo", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("#foo", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormal() {
|
||||||
|
IdType id = new IdType("foo");
|
||||||
|
assertEquals("foo", id.getValueAsString());
|
||||||
|
assertEquals("foo", id.getIdPart());
|
||||||
|
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOid() {
|
||||||
|
IdType id = new IdType("urn:oid:1.2.3.4");
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.getIdPart());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseValueAbsolute() {
|
public void testParseValueAbsolute() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
@ -218,14 +205,6 @@ public class IdTypeDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBigDecimalIds() {
|
|
||||||
|
|
||||||
IdType id = new IdType(new BigDecimal("123"));
|
|
||||||
assertEquals(id.getIdPartAsBigDecimal(), new BigDecimal("123"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseValueAbsoluteWithVersion() {
|
public void testParseValueAbsoluteWithVersion() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
@ -241,30 +220,6 @@ public class IdTypeDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testViewMethods() {
|
|
||||||
IdType i = new IdType("http://foo/fhir/Organization/123/_history/999");
|
|
||||||
assertEquals("Organization/123/_history/999", i.toUnqualified().getValue());
|
|
||||||
assertEquals("http://foo/fhir/Organization/123", i.toVersionless().getValue());
|
|
||||||
assertEquals("Organization/123", i.toUnqualifiedVersionless().getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseValueWithVersion() {
|
|
||||||
Patient patient = new Patient();
|
|
||||||
IdType rr = new IdType();
|
|
||||||
rr.setValue("/123/_history/999");
|
|
||||||
patient.setManagingOrganization(new Reference(rr));
|
|
||||||
|
|
||||||
Patient actual = parseAndEncode(patient);
|
|
||||||
Reference ref = actual.getManagingOrganization();
|
|
||||||
assertEquals(null, ref.getReferenceElement().getResourceType());
|
|
||||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
|
||||||
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseValueMissingType1() {
|
public void testParseValueMissingType1() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
@ -321,10 +276,53 @@ public class IdTypeDstu3Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Patient parseAndEncode(Patient patient) {
|
@Test
|
||||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
public void testParseValueWithVersion() {
|
||||||
ourLog.info("\n" + encoded);
|
Patient patient = new Patient();
|
||||||
return ourCtx.newXmlParser().parseResource(Patient.class, encoded);
|
IdType rr = new IdType();
|
||||||
|
rr.setValue("/123/_history/999");
|
||||||
|
patient.setManagingOrganization(new Reference(rr));
|
||||||
|
|
||||||
|
Patient actual = parseAndEncode(patient);
|
||||||
|
Reference ref = actual.getManagingOrganization();
|
||||||
|
assertEquals(null, ref.getReferenceElement().getResourceType());
|
||||||
|
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||||
|
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUuid() {
|
||||||
|
IdType id = new IdType("urn:uuid:1234-5678");
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.getValueAsString());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.getIdPart());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testViewMethods() {
|
||||||
|
IdType i = new IdType("http://foo/fhir/Organization/123/_history/999");
|
||||||
|
assertEquals("Organization/123/_history/999", i.toUnqualified().getValue());
|
||||||
|
assertEquals("http://foo/fhir/Organization/123", i.toVersionless().getValue());
|
||||||
|
assertEquals("Organization/123", i.toUnqualifiedVersionless().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithVersionNull() {
|
||||||
|
assertEquals("Patient/123", new IdType("Patient/123/_history/2").withVersion("").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -709,13 +709,15 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
|
|||||||
* Creates a new instance of this ID which is identical, but refers to the
|
* Creates a new instance of this ID which is identical, but refers to the
|
||||||
* specific version of this resource ID noted by theVersion.
|
* specific version of this resource ID noted by theVersion.
|
||||||
*
|
*
|
||||||
* @param theVersion The actual version string, e.g. "1"
|
* @param theVersion The actual version string, e.g. "1". If theVersion is blank or null, returns the same as {@link #toVersionless()}}
|
||||||
* @return A new instance of IdType which is identical, but refers to the
|
* @return A new instance of IdType which is identical, but refers to the
|
||||||
* specific version of this resource ID noted by theVersion.
|
* specific version of this resource ID noted by theVersion.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public IdType withVersion(String theVersion) {
|
public IdType withVersion(String theVersion) {
|
||||||
Validate.notBlank(theVersion, "Version may not be null or empty");
|
if (isBlank(theVersion)) {
|
||||||
|
return toVersionless();
|
||||||
|
}
|
||||||
|
|
||||||
if (isLocal() || isUrn()) {
|
if (isLocal() || isUrn()) {
|
||||||
return new IdType(getValueAsString());
|
return new IdType(getValueAsString());
|
||||||
|
@ -12,13 +12,13 @@ import static org.junit.Assert.*;
|
|||||||
|
|
||||||
public class IdTypeR4Test {
|
public class IdTypeR4Test {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdTypeR4Test.class);
|
||||||
private static FhirContext ourCtx;
|
private static FhirContext ourCtx;
|
||||||
|
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(IdTypeR4Test.class);
|
private Patient parseAndEncode(Patient patient) {
|
||||||
|
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
||||||
@AfterClass
|
ourLog.info("\n" + encoded);
|
||||||
public static void afterClassClearContext() {
|
return ourCtx.newXmlParser().parseResource(Patient.class, encoded);
|
||||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -53,79 +53,52 @@ public class IdTypeR4Test {
|
|||||||
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
assertEquals("http://my.org/a/b/c/foo/_history/2", id.withVersion("2").getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBigDecimalIds() {
|
||||||
|
|
||||||
|
IdType id = new IdType(new BigDecimal("123"));
|
||||||
|
assertEquals(id.getIdPartAsBigDecimal(), new BigDecimal("123"));
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUuid() {
|
|
||||||
IdType id = new IdType("urn:uuid:1234-5678");
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.getValueAsString());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.getIdPart());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
|
|
||||||
assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #67
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testOid() {
|
public void testComplicatedLocal() {
|
||||||
IdType id = new IdType("urn:oid:1.2.3.4");
|
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
|
||||||
assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
|
assertTrue(id.isLocal());
|
||||||
assertEquals("urn:oid:1.2.3.4", id.getIdPart());
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
assertNull(id.getResourceType());
|
||||||
assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
|
assertNull(id.getVersionIdPart());
|
||||||
assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
|
assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
|
||||||
assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
|
|
||||||
|
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
|
||||||
|
assertEquals(id, id2);
|
||||||
|
|
||||||
|
id2 = id2.toUnqualified();
|
||||||
|
assertTrue(id2.isLocal());
|
||||||
|
assertNull(id2.getBaseUrl());
|
||||||
|
assertNull(id2.getResourceType());
|
||||||
|
assertNull(id2.getVersionIdPart());
|
||||||
|
assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocal() {
|
public void testConstructorsWithNullArguments() {
|
||||||
IdType id = new IdType("#foo");
|
IdType id = new IdType(null, null, null);
|
||||||
assertEquals("#foo", id.getValueAsString());
|
assertEquals(null, id.getValue());
|
||||||
assertEquals("#foo", id.getIdPart());
|
|
||||||
assertEquals("#foo", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("#foo", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
|
|
||||||
assertEquals("#foo", id.withResourceType("Patient").getValue());
|
|
||||||
assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
|
|
||||||
assertEquals("#foo", id.withVersion("2").getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNormal() {
|
|
||||||
IdType id = new IdType("foo");
|
|
||||||
assertEquals("foo", id.getValueAsString());
|
|
||||||
assertEquals("foo", id.getIdPart());
|
|
||||||
assertEquals("foo", id.toUnqualified().getValueAsString());
|
|
||||||
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
|
||||||
assertEquals(null, id.getVersionIdPart());
|
|
||||||
assertEquals(null, id.getResourceType());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
|
|
||||||
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
|
||||||
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
|
||||||
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetectLocal() {
|
public void testDetectLocal() {
|
||||||
IdType id;
|
IdType id;
|
||||||
|
|
||||||
id = new IdType("#123");
|
id = new IdType("#123");
|
||||||
assertEquals("#123", id.getValue());
|
assertEquals("#123", id.getValue());
|
||||||
assertTrue(id.isLocal());
|
assertTrue(id.isLocal());
|
||||||
|
|
||||||
id = new IdType("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1");
|
id = new IdType("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1");
|
||||||
assertEquals("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1", id.getValue());
|
assertEquals("#Medication/499059CE-CDD4-48BC-9014-528A35D15CED/_history/1", id.getValue());
|
||||||
assertTrue(id.isLocal());
|
assertTrue(id.isLocal());
|
||||||
@ -134,12 +107,6 @@ public class IdTypeR4Test {
|
|||||||
assertEquals("http://example.com/Patient/33#123", id.getValue());
|
assertEquals("http://example.com/Patient/33#123", id.getValue());
|
||||||
assertFalse(id.isLocal());
|
assertFalse(id.isLocal());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConstructorsWithNullArguments() {
|
|
||||||
IdType id = new IdType(null, null, null);
|
|
||||||
assertEquals(null, id.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetectLocalBase() {
|
public void testDetectLocalBase() {
|
||||||
@ -155,32 +122,7 @@ public class IdTypeR4Test {
|
|||||||
assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
|
assertEquals(null, new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getBaseUrl());
|
||||||
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
|
assertEquals("#180f219f-97a8-486d-99d9-ed631fe4fc57", new IdType("#180f219f-97a8-486d-99d9-ed631fe4fc57").getIdPart());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See #67
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testComplicatedLocal() {
|
|
||||||
IdType id = new IdType("#Patient/cid:Patient-72/_history/1");
|
|
||||||
assertTrue(id.isLocal());
|
|
||||||
assertEquals(null, id.getBaseUrl());
|
|
||||||
assertNull(id.getResourceType());
|
|
||||||
assertNull(id.getVersionIdPart());
|
|
||||||
assertEquals("#Patient/cid:Patient-72/_history/1", id.getIdPart());
|
|
||||||
|
|
||||||
IdType id2 = new IdType("#Patient/cid:Patient-72/_history/1");
|
|
||||||
assertEquals(id, id2);
|
|
||||||
|
|
||||||
id2 = id2.toUnqualified();
|
|
||||||
assertTrue(id2.isLocal());
|
|
||||||
assertNull(id2.getBaseUrl());
|
|
||||||
assertNull(id2.getResourceType());
|
|
||||||
assertNull(id2.getVersionIdPart());
|
|
||||||
assertEquals("#Patient/cid:Patient-72/_history/1", id2.getIdPart());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDetermineBase() {
|
public void testDetermineBase() {
|
||||||
|
|
||||||
@ -191,12 +133,67 @@ public class IdTypeR4Test {
|
|||||||
|
|
||||||
rr = new IdType("http://foo/fhir/Organization/123/_history/123");
|
rr = new IdType("http://foo/fhir/Organization/123/_history/123");
|
||||||
assertEquals("http://foo/fhir", rr.getBaseUrl());
|
assertEquals("http://foo/fhir", rr.getBaseUrl());
|
||||||
|
|
||||||
rr = new IdType("Organization/123/_history/123");
|
rr = new IdType("Organization/123/_history/123");
|
||||||
assertEquals(null, rr.getBaseUrl());
|
assertEquals(null, rr.getBaseUrl());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeParts() {
|
||||||
|
IdType id = new IdType("http://foo", "Patient", "123", "456");
|
||||||
|
assertEquals("http://foo/Patient/123/_history/456", id.getValue());
|
||||||
|
assertEquals("http://foo/Patient/123/_history/9", id.withVersion("9").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLocal() {
|
||||||
|
IdType id = new IdType("#foo");
|
||||||
|
assertEquals("#foo", id.getValueAsString());
|
||||||
|
assertEquals("#foo", id.getIdPart());
|
||||||
|
assertEquals("#foo", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("#foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("#foo", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("#foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("#foo", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormal() {
|
||||||
|
IdType id = new IdType("foo");
|
||||||
|
assertEquals("foo", id.getValueAsString());
|
||||||
|
assertEquals("foo", id.getIdPart());
|
||||||
|
assertEquals("foo", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("foo", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("Patient/foo", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("http://foo/Patient/foo", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("foo/_history/2", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOid() {
|
||||||
|
IdType id = new IdType("urn:oid:1.2.3.4");
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.getValueAsString());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.getIdPart());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("urn:oid:1.2.3.4", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseValueAbsolute() {
|
public void testParseValueAbsolute() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
@ -212,14 +209,6 @@ public class IdTypeR4Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBigDecimalIds() {
|
|
||||||
|
|
||||||
IdType id = new IdType(new BigDecimal("123"));
|
|
||||||
assertEquals(id.getIdPartAsBigDecimal(), new BigDecimal("123"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseValueAbsoluteWithVersion() {
|
public void testParseValueAbsoluteWithVersion() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
@ -235,30 +224,6 @@ public class IdTypeR4Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testViewMethods() {
|
|
||||||
IdType i = new IdType("http://foo/fhir/Organization/123/_history/999");
|
|
||||||
assertEquals("Organization/123/_history/999", i.toUnqualified().getValue());
|
|
||||||
assertEquals("http://foo/fhir/Organization/123", i.toVersionless().getValue());
|
|
||||||
assertEquals("Organization/123", i.toUnqualifiedVersionless().getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseValueWithVersion() {
|
|
||||||
Patient patient = new Patient();
|
|
||||||
IdType rr = new IdType();
|
|
||||||
rr.setValue("/123/_history/999");
|
|
||||||
patient.setManagingOrganization(new Reference(rr));
|
|
||||||
|
|
||||||
Patient actual = parseAndEncode(patient);
|
|
||||||
Reference ref = actual.getManagingOrganization();
|
|
||||||
assertEquals(null, ref.getReferenceElement().getResourceType());
|
|
||||||
assertEquals("123", ref.getReferenceElement().getIdPart());
|
|
||||||
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseValueMissingType1() {
|
public void testParseValueMissingType1() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
@ -301,13 +266,6 @@ public class IdTypeR4Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEncodeParts() {
|
|
||||||
IdType id = new IdType("http://foo", "Patient", "123", "456");
|
|
||||||
assertEquals("http://foo/Patient/123/_history/456", id.getValue());
|
|
||||||
assertEquals("http://foo/Patient/123/_history/9", id.withVersion("9").getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseValueRelative2() {
|
public void testParseValueRelative2() {
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
@ -322,10 +280,53 @@ public class IdTypeR4Test {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Patient parseAndEncode(Patient patient) {
|
@Test
|
||||||
String encoded = ourCtx.newXmlParser().encodeResourceToString(patient);
|
public void testParseValueWithVersion() {
|
||||||
ourLog.info("\n" + encoded);
|
Patient patient = new Patient();
|
||||||
return ourCtx.newXmlParser().parseResource(Patient.class, encoded);
|
IdType rr = new IdType();
|
||||||
|
rr.setValue("/123/_history/999");
|
||||||
|
patient.setManagingOrganization(new Reference(rr));
|
||||||
|
|
||||||
|
Patient actual = parseAndEncode(patient);
|
||||||
|
Reference ref = actual.getManagingOrganization();
|
||||||
|
assertEquals(null, ref.getReferenceElement().getResourceType());
|
||||||
|
assertEquals("123", ref.getReferenceElement().getIdPart());
|
||||||
|
assertEquals(null, ref.getReferenceElement().getVersionIdPart());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUuid() {
|
||||||
|
IdType id = new IdType("urn:uuid:1234-5678");
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.getValueAsString());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.getIdPart());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.toUnqualified().getValueAsString());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.toUnqualifiedVersionless().getValueAsString());
|
||||||
|
assertEquals(null, id.getVersionIdPart());
|
||||||
|
assertEquals(null, id.getResourceType());
|
||||||
|
assertEquals(null, id.getBaseUrl());
|
||||||
|
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.withResourceType("Patient").getValue());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.withServerBase("http://foo", "Patient").getValue());
|
||||||
|
assertEquals("urn:uuid:1234-5678", id.withVersion("2").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testViewMethods() {
|
||||||
|
IdType i = new IdType("http://foo/fhir/Organization/123/_history/999");
|
||||||
|
assertEquals("Organization/123/_history/999", i.toUnqualified().getValue());
|
||||||
|
assertEquals("http://foo/fhir/Organization/123", i.toVersionless().getValue());
|
||||||
|
assertEquals("Organization/123", i.toUnqualifiedVersionless().getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithVersionNull() {
|
||||||
|
assertEquals("Patient/123", new IdType("Patient/123/_history/2").withVersion("").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClassClearContext() {
|
||||||
|
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
|
@ -78,6 +78,37 @@
|
|||||||
applies to the operation by name whether it is at the
|
applies to the operation by name whether it is at the
|
||||||
server, type, or instance level.
|
server, type, or instance level.
|
||||||
</action>
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
Calling <![CDATA[<code>IdType#withVersion(String)</code>]]>
|
||||||
|
with a null/blank parameter will now return a copy of the
|
||||||
|
ID with the version removed. Previously this call would
|
||||||
|
deliberately cause an IllegalArgumentException.
|
||||||
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
When updating resources on the JPA server, tags did not always
|
||||||
|
consistently follow FHIR's recommended rules for tag retention. According
|
||||||
|
to FHIR's rules, if a tag is not explicitly present on an update but
|
||||||
|
was present on the previous version, it should be carried forward anyhow.
|
||||||
|
Due to a bug, this happened when more than one tag was present
|
||||||
|
but not when only one was present. This has been corrected. In
|
||||||
|
addition, a new request header called
|
||||||
|
<![CDATA[<code>X-Meta-Snapshot-Mode</code>]]>
|
||||||
|
has been added that can be used by the client to override
|
||||||
|
this behaviour.
|
||||||
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
The JPA server's resource counts query has been optimized to
|
||||||
|
give the database a bit more flexibility to
|
||||||
|
optimize, which should increase performance for this query.
|
||||||
|
</action>
|
||||||
|
<action type="add">
|
||||||
|
The JPA server CapabilityStatement generator has been tuned
|
||||||
|
so that resource counts are no longer calculated synchronously
|
||||||
|
as a part of building the CapabilityStatement response. With
|
||||||
|
this change, counts are calculated in the background and cached
|
||||||
|
which can yield significant performance improvements on
|
||||||
|
hevaily loaded servers.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.3.0" date="2018-03-29">
|
<release version="3.3.0" date="2018-03-29">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user