From 329d0de81006f86e75c8eecff6c5beff7a7d01e7 Mon Sep 17 00:00:00 2001 From: Tim Coffman <234244+timcoffman@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:52:19 -0400 Subject: [PATCH] restoring part of logic for R4, internal linkage searching --- .../SupplementalDataStoreLinkageDstu3.java | 110 +++++++++++++++++- .../r4/SupplementalDataStoreLinkageR4.java | 110 +++++++++++++++++- .../r4b/SupplementalDataStoreLinkageR4B.java | 110 +++++++++++++++++- .../r5/SupplementalDataStoreLinkageR5.java | 110 +++++++++++++++++- 4 files changed, 433 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/ohsu/cmp/ecp/sds/dstu3/SupplementalDataStoreLinkageDstu3.java b/src/main/java/edu/ohsu/cmp/ecp/sds/dstu3/SupplementalDataStoreLinkageDstu3.java index 1c184f2..d96cc27 100644 --- a/src/main/java/edu/ohsu/cmp/ecp/sds/dstu3/SupplementalDataStoreLinkageDstu3.java +++ b/src/main/java/edu/ohsu/cmp/ecp/sds/dstu3/SupplementalDataStoreLinkageDstu3.java @@ -1,5 +1,7 @@ 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; @@ -36,7 +38,6 @@ import edu.ohsu.cmp.ecp.sds.SupplementalDataStoreProperties; import edu.ohsu.cmp.ecp.sds.base.FhirResourceComparison; import edu.ohsu.cmp.ecp.sds.base.SupplementalDataStoreLinkageBase; -import edu.ohsu.cmp.ecp.sds.r4.SupplementalDataStoreLinkageR4; @Component @Conditional(OnDSTU3Condition.class) @@ -57,9 +58,114 @@ public class SupplementalDataStoreLinkageDstu3 extends SupplementalDataStoreLink @Inject IFhirResourceDao daoRelatedPersonDstu3; + private static Predicate 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 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 refersTo( IIdType ref ) { + Predicate p = sameId( ref ) ; + return i -> i.hasResource() && i.getResource().hasReference() && p.test( referenceFromLinkage( i.getResource() ).getReferenceElement() ); + } + + private static Predicate 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 sourceRefersTo( IIdType ref ) { + Predicate p1 = refersTo( ref ) ; + return i -> i.getType() == Linkage.LinkageType.SOURCE && p1.test(i) ; + } + + private Predicate linkageItemFilter( List> 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 linkageSourceFilter( List> 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 convertQueryParameters( List parameters ) { + return parameters.stream().map( this::convertQueryParameter ).collect( toList() ) ; + } + + private List> convertQueryParametersList( List> parameters ) { + return parameters.stream().map( this::convertQueryParameters ).collect( toList() ) ; + } + @Override protected List 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> itemQueryParameter = replacementSearchParameterMap.remove("item"); + List> 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 diff --git a/src/main/java/edu/ohsu/cmp/ecp/sds/r4/SupplementalDataStoreLinkageR4.java b/src/main/java/edu/ohsu/cmp/ecp/sds/r4/SupplementalDataStoreLinkageR4.java index 4b6f93c..fbb5f1a 100644 --- a/src/main/java/edu/ohsu/cmp/ecp/sds/r4/SupplementalDataStoreLinkageR4.java +++ b/src/main/java/edu/ohsu/cmp/ecp/sds/r4/SupplementalDataStoreLinkageR4.java @@ -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; @@ -30,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.OnR4Condition; +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; @@ -55,9 +58,114 @@ public class SupplementalDataStoreLinkageR4 extends SupplementalDataStoreLinkage @Inject IFhirResourceDao daoRelatedPersonR4; + private static Predicate 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 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 refersTo( IIdType ref ) { + Predicate p = sameId( ref ) ; + return i -> i.hasResource() && i.getResource().hasReference() && p.test( referenceFromLinkage( i.getResource() ).getReferenceElement() ); + } + + private static Predicate 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 sourceRefersTo( IIdType ref ) { + Predicate p1 = refersTo( ref ) ; + return i -> i.getType() == Linkage.LinkageType.SOURCE && p1.test(i) ; + } + + private Predicate linkageItemFilter( List> 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 linkageSourceFilter( List> 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 convertQueryParameters( List parameters ) { + return parameters.stream().map( this::convertQueryParameter ).collect( toList() ) ; + } + + private List> convertQueryParametersList( List> parameters ) { + return parameters.stream().map( this::convertQueryParameters ).collect( toList() ) ; + } + @Override protected List searchLinkageResources( SearchParameterMap linkageSearchParamMap, RequestDetails theRequestDetails ) { - 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() ; + List> itemQueryParameter = replacementSearchParameterMap.remove("item"); + List> 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( linkageItemFilter( itemQueryParameter ) ) + .filter( linkageSourceFilter( sourceQueryParameter ) ) + .collect( java.util.stream.Collectors.toList() ) + ; } @Override diff --git a/src/main/java/edu/ohsu/cmp/ecp/sds/r4b/SupplementalDataStoreLinkageR4B.java b/src/main/java/edu/ohsu/cmp/ecp/sds/r4b/SupplementalDataStoreLinkageR4B.java index 658fcf1..a578f5d 100644 --- a/src/main/java/edu/ohsu/cmp/ecp/sds/r4b/SupplementalDataStoreLinkageR4B.java +++ b/src/main/java/edu/ohsu/cmp/ecp/sds/r4b/SupplementalDataStoreLinkageR4B.java @@ -1,5 +1,7 @@ package edu.ohsu.cmp.ecp.sds.r4b; +import static java.util.stream.Collectors.toList; + import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -36,7 +38,6 @@ import edu.ohsu.cmp.ecp.sds.SupplementalDataStoreProperties; import edu.ohsu.cmp.ecp.sds.base.FhirResourceComparison; import edu.ohsu.cmp.ecp.sds.base.SupplementalDataStoreLinkageBase; -import edu.ohsu.cmp.ecp.sds.r4.SupplementalDataStoreLinkageR4; @Component @Conditional(OnR4BCondition.class) @@ -57,9 +58,114 @@ public class SupplementalDataStoreLinkageR4B extends SupplementalDataStoreLinkag @Inject IFhirResourceDao daoRelatedPersonR4B; + private static Predicate 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 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 refersTo( IIdType ref ) { + Predicate p = sameId( ref ) ; + return i -> i.hasResource() && i.getResource().hasReference() && p.test( referenceFromLinkage( i.getResource() ).getReferenceElement() ); + } + + private static Predicate 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 sourceRefersTo( IIdType ref ) { + Predicate p1 = refersTo( ref ) ; + return i -> i.getType() == Linkage.LinkageType.SOURCE && p1.test(i) ; + } + + private Predicate linkageItemFilter( List> 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 linkageSourceFilter( List> 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 convertQueryParameters( List parameters ) { + return parameters.stream().map( this::convertQueryParameter ).collect( toList() ) ; + } + + private List> convertQueryParametersList( List> parameters ) { + return parameters.stream().map( this::convertQueryParameters ).collect( toList() ) ; + } + @Override protected List searchLinkageResources( SearchParameterMap linkageSearchParamMap, RequestDetails theRequestDetails ) { - return daoLinkageR4B.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> itemQueryParameter = replacementSearchParameterMap.remove("item"); + List> sourceQueryParameter = replacementSearchParameterMap.remove("source"); + if ( null != itemQueryParameter ) { + replacementSearchParameterMap.put( "item", convertQueryParametersList( itemQueryParameter ) ); + } + if ( null != sourceQueryParameter ) { + replacementSearchParameterMap.put( "source", convertQueryParametersList( sourceQueryParameter ) ); + } + return daoLinkageR4B.search(replacementSearchParameterMap, theRequestDetails).getAllResources() + .stream() + .filter( linkageItemFilter( itemQueryParameter ) ) + .filter( linkageSourceFilter( sourceQueryParameter ) ) + .collect( java.util.stream.Collectors.toList() ) + ; } @Override diff --git a/src/main/java/edu/ohsu/cmp/ecp/sds/r5/SupplementalDataStoreLinkageR5.java b/src/main/java/edu/ohsu/cmp/ecp/sds/r5/SupplementalDataStoreLinkageR5.java index 6cabff7..bc8ee48 100644 --- a/src/main/java/edu/ohsu/cmp/ecp/sds/r5/SupplementalDataStoreLinkageR5.java +++ b/src/main/java/edu/ohsu/cmp/ecp/sds/r5/SupplementalDataStoreLinkageR5.java @@ -1,5 +1,7 @@ package edu.ohsu.cmp.ecp.sds.r5; +import static java.util.stream.Collectors.toList; + import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -36,7 +38,6 @@ import edu.ohsu.cmp.ecp.sds.SupplementalDataStoreProperties; import edu.ohsu.cmp.ecp.sds.base.FhirResourceComparison; import edu.ohsu.cmp.ecp.sds.base.SupplementalDataStoreLinkageBase; -import edu.ohsu.cmp.ecp.sds.r4.SupplementalDataStoreLinkageR4; @Component @Conditional(OnR5Condition.class) @@ -57,9 +58,114 @@ public class SupplementalDataStoreLinkageR5 extends SupplementalDataStoreLinkage @Inject IFhirResourceDao daoRelatedPersonR5; + private static Predicate 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 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 refersTo( IIdType ref ) { + Predicate p = sameId( ref ) ; + return i -> i.hasResource() && i.getResource().hasReference() && p.test( referenceFromLinkage( i.getResource() ).getReferenceElement() ); + } + + private static Predicate 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 sourceRefersTo( IIdType ref ) { + Predicate p1 = refersTo( ref ) ; + return i -> i.getType() == Linkage.LinkageType.SOURCE && p1.test(i) ; + } + + private Predicate linkageItemFilter( List> 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 linkageSourceFilter( List> 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 convertQueryParameters( List parameters ) { + return parameters.stream().map( this::convertQueryParameter ).collect( toList() ) ; + } + + private List> convertQueryParametersList( List> parameters ) { + return parameters.stream().map( this::convertQueryParameters ).collect( toList() ) ; + } + @Override protected List searchLinkageResources( SearchParameterMap linkageSearchParamMap, RequestDetails theRequestDetails ) { - return daoLinkageR5.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> itemQueryParameter = replacementSearchParameterMap.remove("item"); + List> sourceQueryParameter = replacementSearchParameterMap.remove("source"); + if ( null != itemQueryParameter ) { + replacementSearchParameterMap.put( "item", convertQueryParametersList( itemQueryParameter ) ); + } + if ( null != sourceQueryParameter ) { + replacementSearchParameterMap.put( "source", convertQueryParametersList( sourceQueryParameter ) ); + } + return daoLinkageR5.search(replacementSearchParameterMap, theRequestDetails).getAllResources() + .stream() + .filter( linkageItemFilter( itemQueryParameter ) ) + .filter( linkageSourceFilter( sourceQueryParameter ) ) + .collect( java.util.stream.Collectors.toList() ) + ; } @Override