Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: respect the application property sds.partition.http-header #10

Merged
merged 3 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
@Component
public class SupplementalDataStorePartition {

public static final String HEADER_PARTITION_NAME = "X-Partition-Name";

@Inject
SupplementalDataStoreProperties sdsProperties;

Expand Down Expand Up @@ -80,7 +78,8 @@ public RequestPartitionId partitionIdFromRequest(RequestDetails theRequestDetail
}

protected String partitionNameFromRequest(RequestDetails theRequestDetails) {
final String partitionNameHeaderValue = theRequestDetails.getHeader(HEADER_PARTITION_NAME);
final String httpHeader = sdsProperties.getPartition().getHttpHeader();
final String partitionNameHeaderValue = theRequestDetails.getHeader( httpHeader );
if (StringUtils.isNotBlank(partitionNameHeaderValue)) {
/*
* later we want to recreate the partition name
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
package edu.ohsu.cmp.ecp.sds.dstu3;

import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;

import javax.inject.Inject;

import org.hl7.fhir.instance.model.api.IBaseReference;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.dstu3.model.RelatedPerson;
import org.hl7.fhir.dstu3.model.Type;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.BooleanType;
import org.hl7.fhir.dstu3.model.DomainResource;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Linkage;
import org.hl7.fhir.dstu3.model.Linkage.LinkageType;
import org.hl7.fhir.dstu3.model.Patient;
Expand All @@ -27,6 +32,7 @@
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.starter.annotations.OnDSTU3Condition;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.ReferenceParam;
import edu.ohsu.cmp.ecp.sds.SupplementalDataStoreProperties;
Expand All @@ -52,9 +58,114 @@ public class SupplementalDataStoreLinkageDstu3 extends SupplementalDataStoreLink
@Inject
IFhirResourceDao<org.hl7.fhir.dstu3.model.RelatedPerson> daoRelatedPersonDstu3;

private static Predicate<IIdType> sameId( IIdType id ) {
return (i) -> {
if ( id.hasVersionIdPart() && i.hasVersionIdPart() && !id.getVersionIdPart().equals(i.getVersionIdPart()))
return false ;
if ( id.hasBaseUrl() && i.hasBaseUrl() && !id.getBaseUrl().equals(i.getBaseUrl()))
return false ;
if ( id.hasResourceType() && i.hasResourceType() && !id.getResourceType().equals(i.getResourceType()))
return false ;
if ( !id.hasIdPart() || !i.hasIdPart() )
return false ;
return id.getIdPart().equals( i.getIdPart() ) ;
};
}

private static Predicate<Linkage.LinkageItemComponent> refersTo( IQueryParameterType param ) {
if ( param instanceof ReferenceParam ) {
ReferenceParam refParam = (ReferenceParam)param ;
return refersTo( new IdType( refParam.getResourceType(), refParam.getIdPart() ) ) ;
} else {
return (i) -> false ;
}
}

private static Predicate<Linkage.LinkageItemComponent> refersTo( IIdType ref ) {
Predicate<IIdType> p = sameId( ref ) ;
return i -> i.hasResource() && i.getResource().hasReference() && p.test( referenceFromLinkage( i.getResource() ).getReferenceElement() );
}

private static Predicate<Linkage.LinkageItemComponent> sourceRefersTo( IQueryParameterType param ) {
if ( param instanceof ReferenceParam ) {
ReferenceParam refParam = (ReferenceParam)param ;
return sourceRefersTo( new IdType( refParam.getResourceType(), refParam.getIdPart() ) ) ;
} else {
return (i) -> false ;
}
}

private static Predicate<Linkage.LinkageItemComponent> sourceRefersTo( IIdType ref ) {
Predicate<Linkage.LinkageItemComponent> p1 = refersTo( ref ) ;
return i -> i.getType() == Linkage.LinkageType.SOURCE && p1.test(i) ;
}

private Predicate<IBaseResource> linkageItemFilter( List<List<IQueryParameterType>> parameterValue ) {
if ( null == parameterValue )
return r -> true ;
return r -> {
if ( !(r instanceof Linkage ) )
return false ;
Linkage linkage = (Linkage)r ;

return parameterValue.stream().allMatch( v1 -> v1.stream().anyMatch( v -> linkage.getItem().stream().anyMatch( refersTo( v ) ) ) ) ;
} ;
}

private Predicate<IBaseResource> linkageSourceFilter( List<List<IQueryParameterType>> parameterValue ) {
if ( null == parameterValue )
return r -> true ;
return r -> {
if ( !(r instanceof Linkage ) )
return false ;
Linkage linkage = (Linkage)r ;

return parameterValue.stream().allMatch( v1 -> v1.stream().anyMatch( v -> linkage.getItem().stream().anyMatch( sourceRefersTo( v ) ) ) ) ;
} ;
}

private IQueryParameterType convertQueryParameter( IQueryParameterType parameter ) {
if ( parameter instanceof ReferenceParam ) {
ReferenceParam refParam = (ReferenceParam)parameter ;
IdType id = new IdType( refParam.getValue() ).toUnqualifiedVersionless() ;
return new ReferenceParam( id ) ;
} else {
return parameter ;
}
}

private List<IQueryParameterType> convertQueryParameters( List<IQueryParameterType> parameters ) {
return parameters.stream().map( this::convertQueryParameter ).collect( toList() ) ;
}

private List<List<IQueryParameterType>> convertQueryParametersList( List<List<IQueryParameterType>> parameters ) {
return parameters.stream().map( this::convertQueryParameters ).collect( toList() ) ;
}

@Override
protected List<IBaseResource> searchLinkageResources( SearchParameterMap linkageSearchParamMap, RequestDetails theRequestDetails ) {
return daoLinkageDstu3.search(linkageSearchParamMap, theRequestDetails).getAllResources();
/*
* server is returning LINKAGE resources while searching on SOURCE that match the id but are not SOURCE
*/
/*
* item and source parameters must be relative (i.e. no baseUrl) in order to find these LINKAGE resources
*/

SearchParameterMap replacementSearchParameterMap = linkageSearchParamMap.clone() ;
List<List<IQueryParameterType>> itemQueryParameter = replacementSearchParameterMap.remove("item");
List<List<IQueryParameterType>> sourceQueryParameter = replacementSearchParameterMap.remove("source");
if ( null != itemQueryParameter ) {
replacementSearchParameterMap.put( "item", convertQueryParametersList( itemQueryParameter ) );
}
if ( null != sourceQueryParameter ) {
replacementSearchParameterMap.put( "source", convertQueryParametersList( sourceQueryParameter ) );
}
return daoLinkageDstu3.search(replacementSearchParameterMap, theRequestDetails).getAllResources()
.stream()
.filter( linkageItemFilter( itemQueryParameter ) )
.filter( linkageSourceFilter( sourceQueryParameter ) )
.collect( java.util.stream.Collectors.toList() )
;
}

@Override
Expand All @@ -64,8 +175,9 @@ protected List<IBaseResource> filterLinkageResourcesHavingAlternateItem( List<IB
if (res instanceof Linkage) {
Linkage linkage = (Linkage) res;
for (Linkage.LinkageItemComponent linkageItem : linkage.getItem()) {
if (linkageItem.getType() == LinkageType.ALTERNATE && linkageItem.hasResource() && linkageItem.getResource().hasReference() && nonLocalPatientId.equals(linkageItem.getResource().getReferenceElement())) {
if (linkageItem.getType() == LinkageType.ALTERNATE && linkageItem.hasResource() && linkageItem.getResource().hasReference() && nonLocalPatientId.equals( referenceFromLinkage( linkageItem.getResource() ).getReferenceElement())) {
linkageResources.add(res);
break; // breaking to prevent re-adding res if there are multiple alternates
}
}
}
Expand All @@ -87,12 +199,37 @@ protected List<Reference> patientsFromLinkageResources(List<IBaseResource> linka
return linkedPatients;
}

private static Reference referenceFromLinkage( Reference ref ) {
if ( !ref.hasExtension(EXTENSION_URL_SDS_PARTITION_NAME) )
return ref ;
if ( !ref.hasReferenceElement() )
return ref ;
Type extValue = ref.getExtensionByUrl(EXTENSION_URL_SDS_PARTITION_NAME).getValue() ;
if ( !(extValue instanceof StringType) )
return ref ;
IIdType id = new IdType( ((StringType)extValue).getValue(), ref.getReferenceElement().getResourceType(), ref.getReferenceElement().getIdPart(), ref.getReferenceElement().getVersionIdPart() ) ;
return new Reference( id ) ;
}

private static Reference referenceForLinkage( IIdType id ) {
if ( id.hasBaseUrl() ) {
Reference ref = new Reference( id.toUnqualifiedVersionless() ) ;
ref.addExtension(EXTENSION_URL_SDS_PARTITION_NAME, new StringType( id.getBaseUrl() ) );
return ref ;
} else {
return new Reference(id) ;
}
}

@Override
protected void createLinkage( IIdType sourcePatientId, IIdType alternatePatientId, RequestDetails theRequestDetails ) {
Linkage linkage = new Linkage();
linkage.addItem().setType(LinkageType.SOURCE).setResource(new Reference(sourcePatientId));
linkage.addItem().setType(LinkageType.ALTERNATE).setResource(new Reference(alternatePatientId));
daoLinkageDstu3.create(linkage, theRequestDetails);
linkage.addItem().setType(LinkageType.SOURCE).setResource(referenceForLinkage(sourcePatientId));
linkage.addItem().setType(LinkageType.ALTERNATE).setResource(referenceForLinkage(alternatePatientId));
DaoMethodOutcome outcome = daoLinkageDstu3.create(linkage, theRequestDetails);
if ( Boolean.TRUE != outcome.getCreated() ) {
throw new RuntimeException( "failed to create linkage between " + sourcePatientId + " and " + alternatePatientId ) ;
}
}

@Override
Expand All @@ -104,6 +241,7 @@ protected Set<? extends IBaseReference> alternatePatientsFromLinkageResources(Li
.flatMap(k -> k.getItem().stream())
.filter(i -> i.getType() == LinkageType.ALTERNATE)
.map(i -> i.getResource())
.map( SupplementalDataStoreLinkageDstu3::referenceFromLinkage )
.collect(java.util.stream.Collectors.toList());
return FhirResourceComparison.references().createSet( sourceRefs ) ;
}
Expand All @@ -117,6 +255,7 @@ protected Set<? extends IBaseReference> sourcePatientsFromLinkageResources(List<
.flatMap(k -> k.getItem().stream())
.filter(i -> i.getType() == LinkageType.SOURCE)
.map(i -> i.getResource())
.map( SupplementalDataStoreLinkageDstu3::referenceFromLinkage )
.collect(java.util.stream.Collectors.toList());
return FhirResourceComparison.references().createSet( sourceRefs ) ;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package edu.ohsu.cmp.ecp.sds.r4;

import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -31,7 +33,6 @@
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.starter.annotations.OnR4Condition;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.ReferenceParam;
import edu.ohsu.cmp.ecp.sds.SupplementalDataStoreProperties;
Expand Down Expand Up @@ -70,7 +71,7 @@ private static Predicate<IIdType> sameId( IIdType id ) {
return id.getIdPart().equals( i.getIdPart() ) ;
};
}

private static Predicate<Linkage.LinkageItemComponent> refersTo( IQueryParameterType param ) {
if ( param instanceof ReferenceParam ) {
ReferenceParam refParam = (ReferenceParam)param ;
Expand All @@ -79,7 +80,7 @@ private static Predicate<Linkage.LinkageItemComponent> refersTo( IQueryParameter
return (i) -> false ;
}
}

private static Predicate<Linkage.LinkageItemComponent> refersTo( IIdType ref ) {
Predicate<IIdType> p = sameId( ref ) ;
return i -> i.hasResource() && i.getResource().hasReference() && p.test( referenceFromLinkage( i.getResource() ).getReferenceElement() );
Expand All @@ -93,54 +94,78 @@ private static Predicate<Linkage.LinkageItemComponent> sourceRefersTo( IQueryPar
return (i) -> false ;
}
}


private static Predicate<Linkage.LinkageItemComponent> sourceRefersTo( IIdType ref ) {
Predicate<Linkage.LinkageItemComponent> p1 = refersTo( ref ) ;
return i -> i.getType() == Linkage.LinkageType.SOURCE && p1.test(i) ;
}

private Predicate<IBaseResource> linkageItemFilter( List<List<IQueryParameterType>> parameterValue ) {
if ( null == parameterValue )
return r -> true ;
return r -> {
if ( !(r instanceof Linkage ) )
return false ;
Linkage linkage = (Linkage)r ;

return parameterValue.stream().allMatch( v1 -> v1.stream().anyMatch( v -> linkage.getItem().stream().anyMatch( refersTo( v ) ) ) ) ;
} ;
}

private Predicate<IBaseResource> linkageSourceFilter( List<List<IQueryParameterType>> parameterValue ) {
if ( null == parameterValue )
return r -> true ;
return r -> {
if ( !(r instanceof Linkage ) )
return false ;
Linkage linkage = (Linkage)r ;

return parameterValue.stream().allMatch( v1 -> v1.stream().anyMatch( v -> linkage.getItem().stream().anyMatch( sourceRefersTo( v ) ) ) ) ;
} ;
}


private IQueryParameterType convertQueryParameter( IQueryParameterType parameter ) {
if ( parameter instanceof ReferenceParam ) {
ReferenceParam refParam = (ReferenceParam)parameter ;
IdType id = new IdType( refParam.getValue() ).toUnqualifiedVersionless() ;
return new ReferenceParam( id ) ;
} else {
return parameter ;
}
}

private List<IQueryParameterType> convertQueryParameters( List<IQueryParameterType> parameters ) {
return parameters.stream().map( this::convertQueryParameter ).collect( toList() ) ;
}

private List<List<IQueryParameterType>> convertQueryParametersList( List<List<IQueryParameterType>> parameters ) {
return parameters.stream().map( this::convertQueryParameters ).collect( toList() ) ;
}

@Override
protected List<IBaseResource> searchLinkageResources( SearchParameterMap linkageSearchParamMap, RequestDetails theRequestDetails ) {
/*
* server is failing to find existing LINKAGE resources while searching on ITEM
*
return daoLinkageR4.search(linkageSearchParamMap, theRequestDetails).getAllResources();
* server is returning LINKAGE resources while searching on SOURCE that match the id but are not SOURCE
*/
/*
* item and source parameters must be relative (i.e. no baseUrl) in order to find these LINKAGE resources
*/

SearchParameterMap replacementSearchParameterMap = linkageSearchParamMap.clone() ;
Predicate<IBaseResource> itemFilter = linkageItemFilter( replacementSearchParameterMap.remove("item") ) ;
Predicate<IBaseResource> sourceFilter = linkageSourceFilter( replacementSearchParameterMap.remove("source") ) ;
List<List<IQueryParameterType>> itemQueryParameter = replacementSearchParameterMap.remove("item");
List<List<IQueryParameterType>> sourceQueryParameter = replacementSearchParameterMap.remove("source");
if ( null != itemQueryParameter ) {
replacementSearchParameterMap.put( "item", convertQueryParametersList( itemQueryParameter ) );
}
if ( null != sourceQueryParameter ) {
replacementSearchParameterMap.put( "source", convertQueryParametersList( sourceQueryParameter ) );
}
return daoLinkageR4.search(replacementSearchParameterMap, theRequestDetails).getAllResources()
.stream()
.filter( itemFilter )
.filter( sourceFilter )
.filter( linkageItemFilter( itemQueryParameter ) )
.filter( linkageSourceFilter( sourceQueryParameter ) )
.collect( java.util.stream.Collectors.toList() )
;

}

@Override
Expand Down
Loading
Loading