diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/DhisFindException.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/DhisFindException.java new file mode 100644 index 00000000..089f6a14 --- /dev/null +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/DhisFindException.java @@ -0,0 +1,44 @@ +package org.dhis2.fhir.adapter.dhis; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Thrown if the find operation caused a conflict or a bad request on the server. + * + * @author volsch + */ +public class DhisFindException extends RuntimeException +{ + private static final long serialVersionUID = 565765406720494135L; + + public DhisFindException( String message, Throwable cause ) + { + super( message, cause ); + } +} diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/UriFilterApplier.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/UriFilterApplier.java new file mode 100644 index 00000000..0f0fa477 --- /dev/null +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/UriFilterApplier.java @@ -0,0 +1,45 @@ +package org.dhis2.fhir.adapter.dhis.model; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.springframework.web.util.UriBuilder; + +import javax.annotation.Nonnull; +import java.util.List; + +/** + * Applies a filter to a URI builder. + * + * @author volsch + */ +public interface UriFilterApplier +{ + @Nonnull + T add( @Nonnull T uriBuilder, @Nonnull List variables ); +} diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/OrganizationUnitService.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/OrganizationUnitService.java index 20436aa7..379b4d92 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/OrganizationUnitService.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/OrganizationUnitService.java @@ -32,6 +32,7 @@ import org.dhis2.fhir.adapter.dhis.metadata.model.DhisSyncGroup; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; import javax.annotation.Nonnull; import java.time.Instant; @@ -54,7 +55,7 @@ public interface OrganizationUnitService Optional findOneRefreshedByReference( @Nonnull Reference reference ); @Nonnull - DhisResourceResult find( int from, int max ); + DhisResourceResult find( @Nonnull UriFilterApplier uriFilterApplier, int from, int max ); @Nonnull Instant poll( @Nonnull DhisSyncGroup group, @Nonnull Instant lastUpdated, int toleranceMillis, diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganizationUnitServiceImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganizationUnitServiceImpl.java index 35c9a753..76607ff1 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganizationUnitServiceImpl.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/orgunit/impl/OrganizationUnitServiceImpl.java @@ -30,9 +30,11 @@ import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.dhis2.fhir.adapter.data.model.ProcessedItemInfo; +import org.dhis2.fhir.adapter.dhis.DhisFindException; import org.dhis2.fhir.adapter.dhis.metadata.model.DhisSyncGroup; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnit; import org.dhis2.fhir.adapter.dhis.orgunit.OrganizationUnitService; import org.dhis2.fhir.adapter.dhis.util.DhisPagingQuery; @@ -42,6 +44,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; @@ -51,8 +54,10 @@ import javax.annotation.Nonnull; import java.time.Instant; import java.time.ZoneId; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -130,13 +135,27 @@ public Optional findOneRefreshedByReference( @Nonnull Referenc @HystrixCommand @Nonnull @Override - public DhisResourceResult find( int from, int max ) + public DhisResourceResult find( @Nonnull UriFilterApplier uriFilterApplier, int from, int max ) { final DhisPagingQuery pagingQuery = DhisPagingUtils.createPagingQuery( from, max ); - final String uri = UriComponentsBuilder.newInstance().path( "/organisationUnits.json" ) + final List variables = new ArrayList<>(); + final String uri = uriFilterApplier.add( UriComponentsBuilder.newInstance(), variables ).path( "/organisationUnits.json" ) .queryParam( "paging", "true" ).queryParam( "page", pagingQuery.getPage() ).queryParam( "pageSize", pagingQuery.getPageSize() ) - .queryParam( "order", "id" ).queryParam( "fields", FIELDS ).toUriString(); - final ResponseEntity result = restTemplate.getForEntity( uri, DhisOrganizationUnits.class ); + .queryParam( "order", "id" ).queryParam( "fields", FIELDS ).build( false ).toString(); + + final ResponseEntity result; + try + { + result = restTemplate.getForEntity( uri, DhisOrganizationUnits.class, variables.toArray() ); + } + catch ( HttpClientErrorException e ) + { + if ( e.getStatusCode() == HttpStatus.BAD_REQUEST || e.getStatusCode() == HttpStatus.CONFLICT ) + { + throw new DhisFindException( e.getMessage(), e ); + } + throw e; + } final DhisOrganizationUnits organizationUnits = Objects.requireNonNull( result.getBody() ); return new DhisResourceResult<>( (organizationUnits.getOrganizationUnits().size() > pagingQuery.getResultOffset()) ? diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/EventService.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/EventService.java index 8758a0d7..d1e9427a 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/EventService.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/EventService.java @@ -31,6 +31,7 @@ import org.dhis2.fhir.adapter.data.model.ProcessedItemInfo; import org.dhis2.fhir.adapter.dhis.metadata.model.DhisSyncGroup; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; import javax.annotation.Nonnull; import java.time.Instant; @@ -62,7 +63,7 @@ List find( @Nonnull String programId, @Nonnull String programStageId, Event createOrMinimalUpdate( @Nonnull Event event ); @Nonnull - DhisResourceResult find( @Nonnull String programId, @Nonnull String programStageId, int from, int max ); + DhisResourceResult find( @Nonnull String programId, @Nonnull String programStageId, @Nonnull UriFilterApplier uriFilterApplier, int from, int max ); @Nonnull Instant poll( @Nonnull DhisSyncGroup group, @Nonnull Instant lastUpdated, int toleranceMillis, diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/EventServiceImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/EventServiceImpl.java index d06b5f1f..314a3274 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/EventServiceImpl.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/impl/EventServiceImpl.java @@ -32,12 +32,14 @@ import org.apache.commons.lang3.ObjectUtils; import org.dhis2.fhir.adapter.data.model.ProcessedItemInfo; import org.dhis2.fhir.adapter.dhis.DhisConflictException; +import org.dhis2.fhir.adapter.dhis.DhisFindException; import org.dhis2.fhir.adapter.dhis.DhisImportUnsuccessfulException; import org.dhis2.fhir.adapter.dhis.metadata.model.DhisSyncGroup; import org.dhis2.fhir.adapter.dhis.model.DataValue; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; import org.dhis2.fhir.adapter.dhis.model.ImportSummaryWebMessage; import org.dhis2.fhir.adapter.dhis.model.Status; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; import org.dhis2.fhir.adapter.dhis.tracker.program.Event; import org.dhis2.fhir.adapter.dhis.tracker.program.EventService; import org.dhis2.fhir.adapter.dhis.util.DhisPagingQuery; @@ -57,6 +59,7 @@ import javax.annotation.Nonnull; import java.time.Instant; import java.time.ZoneId; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -223,13 +226,27 @@ protected Event update( @Nonnull Event event ) @Nonnull @Override - public DhisResourceResult find( @Nonnull String programId, @Nonnull String programStageId, int from, int max ) + public DhisResourceResult find( @Nonnull String programId, @Nonnull String programStageId, @Nonnull UriFilterApplier uriFilterApplier, int from, int max ) { final DhisPagingQuery pagingQuery = DhisPagingUtils.createPagingQuery( from, max ); - final String uri = UriComponentsBuilder.newInstance().path( "/events.json" ) + final List variables = new ArrayList<>(); + final String uri = uriFilterApplier.add( UriComponentsBuilder.newInstance(), variables ).path( "/events.json" ) .queryParam( "skipPaging", "false" ).queryParam( "page", pagingQuery.getPage() ).queryParam( "pageSize", pagingQuery.getPageSize() ) - .queryParam( "program", programId ).queryParam( "programStage", programStageId ).queryParam( "ouMode", "ACCESSIBLE" ).queryParam( "fields", FIELDS ).toUriString(); - final ResponseEntity result = restTemplate.getForEntity( uri, DhisEvents.class ); + .queryParam( "program", programId ).queryParam( "programStage", programStageId ).queryParam( "ouMode", "ACCESSIBLE" ).queryParam( "fields", FIELDS ) + .build().toString(); + final ResponseEntity result; + try + { + result = restTemplate.getForEntity( uri, DhisEvents.class, variables.toArray() ); + } + catch ( HttpClientErrorException e ) + { + if ( e.getStatusCode() == HttpStatus.BAD_REQUEST || e.getStatusCode() == HttpStatus.CONFLICT ) + { + throw new DhisFindException( e.getMessage(), e ); + } + throw e; + } final DhisEvents events = Objects.requireNonNull( result.getBody() ); return new DhisResourceResult<>( (events.getEvents().size() > pagingQuery.getResultOffset()) ? diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityService.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityService.java index 05daf63c..ffe61734 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityService.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityService.java @@ -31,6 +31,7 @@ import org.dhis2.fhir.adapter.data.model.ProcessedItemInfo; import org.dhis2.fhir.adapter.dhis.metadata.model.DhisSyncGroup; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; import javax.annotation.Nonnull; import java.time.Instant; @@ -65,7 +66,7 @@ Collection findByAttrValue( @Nonnull String typeId, TrackedEntityInstance createOrUpdate( @Nonnull TrackedEntityInstance trackedEntityInstance ); @Nonnull - DhisResourceResult find( @Nonnull String trackedEntityTypeId, int from, int max ); + DhisResourceResult find( @Nonnull String trackedEntityTypeId, @Nonnull UriFilterApplier uriFilterApplier, int from, int max ); @Nonnull Instant poll( @Nonnull DhisSyncGroup group, @Nonnull Instant lastUpdated, int toleranceMillis, diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java index c1070906..557031a4 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/impl/TrackedEntityServiceImpl.java @@ -32,6 +32,7 @@ import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheKey; import org.dhis2.fhir.adapter.data.model.ProcessedItemInfo; import org.dhis2.fhir.adapter.dhis.DhisConflictException; +import org.dhis2.fhir.adapter.dhis.DhisFindException; import org.dhis2.fhir.adapter.dhis.DhisImportUnsuccessfulException; import org.dhis2.fhir.adapter.dhis.DhisResourceException; import org.dhis2.fhir.adapter.dhis.metadata.model.DhisSyncGroup; @@ -40,6 +41,7 @@ import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.dhis.model.ImportSummaryWebMessage; import org.dhis2.fhir.adapter.dhis.model.Status; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; import org.dhis2.fhir.adapter.dhis.sync.DhisLastUpdated; import org.dhis2.fhir.adapter.dhis.sync.StoredDhisResourceService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.RequiredValueType; @@ -68,8 +70,10 @@ import javax.annotation.Nonnull; import java.time.Instant; import java.time.ZoneId; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -215,13 +219,26 @@ public TrackedEntityInstance createOrUpdate( @Nonnull TrackedEntityInstance trac @Nonnull @Override - public DhisResourceResult find( @Nonnull String trackedEntityTypeId, int from, int max ) + public DhisResourceResult find( @Nonnull String trackedEntityTypeId, @Nonnull UriFilterApplier uriFilterApplier, int from, int max ) { final DhisPagingQuery pagingQuery = DhisPagingUtils.createPagingQuery( from, max ); - final String uri = UriComponentsBuilder.newInstance().path( "/trackedEntityInstances.json" ) + final List variables = new ArrayList<>(); + final String uri = uriFilterApplier.add( UriComponentsBuilder.newInstance(), variables ).path( "/trackedEntityInstances.json" ) .queryParam( "skipPaging", "false" ).queryParam( "page", pagingQuery.getPage() ).queryParam( "pageSize", pagingQuery.getPageSize() ) - .queryParam( "trackedEntityType", trackedEntityTypeId ).queryParam( "ouMode", "ACCESSIBLE" ).queryParam( "fields", TEI_FIELDS ).toUriString(); - final ResponseEntity result = restTemplate.getForEntity( uri, TrackedEntityInstances.class ); + .queryParam( "trackedEntityType", trackedEntityTypeId ).queryParam( "ouMode", "ACCESSIBLE" ).queryParam( "fields", TEI_FIELDS ).build().toString(); + final ResponseEntity result; + try + { + result = restTemplate.getForEntity( uri, TrackedEntityInstances.class, variables.toArray() ); + } + catch ( HttpClientErrorException e ) + { + if ( e.getStatusCode() == HttpStatus.BAD_REQUEST || e.getStatusCode() == HttpStatus.CONFLICT ) + { + throw new DhisFindException( e.getMessage(), e ); + } + throw e; + } final TrackedEntityInstances instances = Objects.requireNonNull( result.getBody() ); return new DhisResourceResult<>( (instances.getTrackedEntityInstances().size() > pagingQuery.getResultOffset()) ? diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ConditionResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ConditionResourceProvider.java index 46dbd1f2..bd05c339 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ConditionResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ConditionResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = Condition.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3DiagnosticReportResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3DiagnosticReportResourceProvider.java index 3f428a91..8c3e5dd2 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3DiagnosticReportResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3DiagnosticReportResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = DiagnosticReport.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3EncounterResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3EncounterResourceProvider.java index 74628bd9..c635ee56 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3EncounterResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3EncounterResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ImmunizationResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ImmunizationResourceProvider.java index 0ff10d46..82e33156 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ImmunizationResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ImmunizationResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = Immunization.SP_VACCINE_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3LocationResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3LocationResourceProvider.java index 162d683a..5b3b5cd5 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3LocationResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3LocationResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3MedicationRequestResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3MedicationRequestResourceProvider.java index 64771656..fc0e023c 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3MedicationRequestResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3MedicationRequestResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = MedicationRequest.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ObservationResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ObservationResourceProvider.java index 27248142..b1042f0e 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ObservationResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3ObservationResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = Observation.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3OrganizationResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3OrganizationResourceProvider.java index cae263b2..ec2bd0e4 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3OrganizationResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3OrganizationResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PatientResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PatientResourceProvider.java index ed103696..c9fb1444 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PatientResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PatientResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PractitionerResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PractitionerResourceProvider.java index bab49759..eb2bfe4a 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PractitionerResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3PractitionerResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3RelatedPersonResourceProvider.java b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3RelatedPersonResourceProvider.java index 13ff3e7a..b33a4bcb 100644 --- a/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3RelatedPersonResourceProvider.java +++ b/fhir-dstu3/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/dstu3/Dstu3RelatedPersonResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * DSTU3 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.DSTU3; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ConditionResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ConditionResourceProvider.java index f1a5d781..ee71401f 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ConditionResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ConditionResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = Condition.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4DiagnosticReportResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4DiagnosticReportResourceProvider.java index f3f490a2..61a82ced 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4DiagnosticReportResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4DiagnosticReportResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = DiagnosticReport.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4EncounterResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4EncounterResourceProvider.java index afddf2e2..b5d4d3b7 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4EncounterResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4EncounterResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ImmunizationResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ImmunizationResourceProvider.java index a6b5349b..c03d614f 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ImmunizationResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ImmunizationResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = Immunization.SP_VACCINE_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4LocationResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4LocationResourceProvider.java index 92bfa5a6..5c53b491 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4LocationResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4LocationResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4MedicationRequestResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4MedicationRequestResourceProvider.java index 994971df..e99821ef 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4MedicationRequestResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4MedicationRequestResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = MedicationRequest.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ObservationResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ObservationResourceProvider.java index aa9508f6..db281670 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ObservationResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4ObservationResourceProvider.java @@ -28,6 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +45,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +69,12 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = Observation.SP_CODE ) TokenOrListParam filteredCodes, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, + @Nullable @RawParam Map> filter ) + { + return super.search( count, filteredCodes, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4OrganizationResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4OrganizationResourceProvider.java index c34a91c7..341a4571 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4OrganizationResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4OrganizationResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PatientResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PatientResourceProvider.java index e6d29f85..3e0e4d02 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PatientResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PatientResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PractitionerResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PractitionerResourceProvider.java index c4ef6cf2..c5f881ca 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PractitionerResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4PractitionerResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4RelatedPersonResourceProvider.java b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4RelatedPersonResourceProvider.java index 06aee357..79befa1a 100644 --- a/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4RelatedPersonResourceProvider.java +++ b/fhir-r4/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/r4/R4RelatedPersonResourceProvider.java @@ -28,6 +28,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.annotation.Count; +import ca.uhn.fhir.rest.annotation.OptionalParam; +import ca.uhn.fhir.rest.annotation.RawParam; +import ca.uhn.fhir.rest.annotation.Search; +import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.FhirVersion; @@ -38,6 +44,9 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; /** * r4 resource provider. @@ -59,4 +68,11 @@ public FhirVersion getFhirVersion() { return FhirVersion.R4; } + + @Search( allowUnknownParams = true ) + @Nonnull + public IBundleProvider search( @Nullable @Count Integer count, @Nullable @OptionalParam( name = SP_LAST_UPDATED ) DateRangeParam lastUpdatedDateRange, @Nullable @RawParam Map> filter ) + { + return search( count, null, lastUpdatedDateRange, filter ); + } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java index 5a67d067..6e4721ee 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/AbstractRule.java @@ -155,6 +155,8 @@ public abstract class AbstractRule extends VersionedBaseMetadata implements Seri private ExecutableScript transformExpScript; + private ExecutableScript filterScript; + private boolean containedAllowed; private boolean grouping; @@ -278,6 +280,19 @@ public void setApplicableExpScript( ExecutableScript applicableOutScript ) this.applicableExpScript = applicableOutScript; } + @JsonCacheId + @ManyToOne + @JoinColumn( name = "filter_script_id", referencedColumnName = "id" ) + public ExecutableScript getFilterScript() + { + return filterScript; + } + + public void setFilterScript( ExecutableScript filterScript ) + { + this.filterScript = filterScript; + } + @Basic @Column( name = "imp_enabled", nullable = false, columnDefinition = "BOOLEAN DEFAULT TRUE NOT NULL" ) public boolean isImpEnabled() diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptType.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptType.java index a5a4fae1..88c69b91 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptType.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptType.java @@ -53,5 +53,10 @@ public enum ScriptType /** * Transforms a FHIR resource to a FHIR resource. */ - TRANSFORM_FHIR + TRANSFORM_FHIR, + + /** + * Converts the search filter. + */ + SEARCH_FILTER } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java index 5a4f166b..a7de2fe6 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/metadata/model/ScriptVariable.java @@ -56,7 +56,8 @@ public enum ScriptVariable ORGANIZATION_UNIT_ID( "organizationUnitId" ), ORGANIZATION_UNIT( "organizationUnit" ), ORGANIZATION_UNIT_RESOLVER( "organizationUnitResolver" ), - TEI_FHIR_RESOURCE( "teiFhirResource" ); + TEI_FHIR_RESOURCE( "teiFhirResource" ), + SEARCH_FILTER( "searchFilter" ); private final String variableName; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisRepository.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisRepository.java index 72db19af..b65c34bc 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisRepository.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/DhisRepository.java @@ -29,6 +29,7 @@ */ import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.dhis.metadata.model.DhisSyncGroup; import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; @@ -39,6 +40,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -59,6 +61,6 @@ public interface DhisRepository Optional readByIdentifier( @Nonnull FhirClient fhirClient, @Nonnull FhirResourceType fhirResourceType, @Nonnull String identifier ); @Nonnull - IBundleProvider search( @Nonnull FhirClient fhirClient, @Nonnull FhirResourceType fhirResourceType, @Nullable Set filteredCodes, @Nonnull Map filter, Integer count ) + IBundleProvider search( @Nonnull FhirClient fhirClient, @Nonnull FhirResourceType fhirResourceType, Integer count, @Nullable Set filteredCodes, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange ) throws DhisToFhirDataProviderException; } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/DhisRepositoryImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/DhisRepositoryImpl.java index e60e70cb..015983d2 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/DhisRepositoryImpl.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/repository/impl/DhisRepositoryImpl.java @@ -29,6 +29,7 @@ */ import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.server.SimpleBundleProvider; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.dhis2.fhir.adapter.auth.Authorization; @@ -231,7 +232,8 @@ protected DhisResource getDhisResource() @HystrixCommand( ignoreExceptions = { MissingDhisResourceException.class, TransformerDataException.class, TransformerMappingException.class, DhisToFhirDataProviderException.class, UnauthorizedException.class, ForbiddenException.class } ) @Nonnull @Override - public IBundleProvider search( @Nonnull FhirClient fhirClient, @Nonnull FhirResourceType fhirResourceType, @Nullable Set filteredCodes, @Nonnull Map filter, Integer count ) throws DhisToFhirDataProviderException + public IBundleProvider search( @Nonnull FhirClient fhirClient, @Nonnull FhirResourceType fhirResourceType, Integer count, @Nullable Set filteredCodes, + @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange ) throws DhisToFhirDataProviderException { final int resultingCount; if ( count == null ) @@ -262,7 +264,7 @@ else if ( dhisResourceTypes.size() > 1 ) } else { - result = search( fhirClient, fhirResourceType, filteredCodes, filter, dhisResourceTypes.stream().findFirst().get(), rules, resultingCount ); + result = search( fhirClient, fhirResourceType, filteredCodes, filter, lastUpdatedDateRange, dhisResourceTypes.stream().findFirst().get(), rules, resultingCount ); } } } @@ -274,7 +276,7 @@ else if ( dhisResourceTypes.size() > 1 ) } @Nonnull - protected List search( @Nonnull FhirClient fhirClient, @Nonnull FhirResourceType fhirResourceType, @Nullable Set filteredCodes, @Nonnull Map filter, + protected List search( @Nonnull FhirClient fhirClient, @Nonnull FhirResourceType fhirResourceType, @Nullable Set filteredCodes, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, @Nonnull DhisResourceType dhisResourceType, @Nonnull List> rules, int count ) { if ( count == 0 ) @@ -283,7 +285,7 @@ protected List search( @Nonnull FhirClient fhirClient, @Nonnull F } final DhisToFhirDataProvider dataProvider = dhisToFhirTransformerService.getDataProvider( dhisResourceType ); - final PreparedDhisToFhirSearch preparedSearch = dataProvider.prepareSearchCasted( rules, filter, count ); + final PreparedDhisToFhirSearch preparedSearch = dataProvider.prepareSearchCasted( fhirClient.getFhirVersion(), rules, filter, lastUpdatedDateRange, count ); final LinkedList dhisResources = new LinkedList<>(); final List result = new ArrayList<>(); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractReadOnlyResourceProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractReadOnlyResourceProvider.java index 6192d9d9..089b5d50 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractReadOnlyResourceProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/server/provider/AbstractReadOnlyResourceProvider.java @@ -28,12 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import ca.uhn.fhir.rest.annotation.Count; import ca.uhn.fhir.rest.annotation.IdParam; import ca.uhn.fhir.rest.annotation.Read; import ca.uhn.fhir.rest.annotation.RequiredParam; import ca.uhn.fhir.rest.annotation.Search; import ca.uhn.fhir.rest.api.server.IBundleProvider; +import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.TokenOrListParam; import ca.uhn.fhir.rest.param.TokenParam; import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -46,6 +47,7 @@ import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientResourceRepository; import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirClientSystemRepository; import org.dhis2.fhir.adapter.fhir.model.SingleFhirVersionRestricted; +import org.dhis2.fhir.adapter.fhir.model.SystemCodeValue; import org.dhis2.fhir.adapter.fhir.repository.DhisFhirResourceId; import org.dhis2.fhir.adapter.fhir.repository.DhisRepository; import org.dhis2.fhir.adapter.fhir.repository.FhirRepository; @@ -57,7 +59,10 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.function.Supplier; @@ -72,6 +77,8 @@ public abstract class AbstractReadOnlyResourceProvider { public static final String SP_IDENTIFIER = "identifier"; + public static final String SP_LAST_UPDATED = "_lastUpdated"; + private final Class resourceClass; private final FhirRepository fhirRepository; @@ -138,13 +145,24 @@ public List searchByIdentifier( @Nonnull @RequiredParam( name = SP_IDENTIFIER } ); } - @Search @Nonnull - public IBundleProvider search( @Count Integer count ) + protected IBundleProvider search( @Nullable Integer count, @Nullable TokenOrListParam filteredCodes, @Nullable DateRangeParam lastUpdatedDateRange, @Nullable Map> filter ) { + final Set convertedFilteredCodes; + if ( ( filteredCodes == null ) || filteredCodes.getValuesAsQueryTokens().isEmpty() ) + { + convertedFilteredCodes = null; + } + else + { + convertedFilteredCodes = new HashSet<>(); + filteredCodes.getValuesAsQueryTokens().forEach( tp -> + convertedFilteredCodes.add( new SystemCodeValue( StringUtils.defaultString( tp.getSystem() ), StringUtils.defaultString( tp.getValue() ) ) ) ); + } + return executeInSecurityContext( () -> getDhisRepository().search( getFhirClientResource().getFhirClient(), getFhirResourceType(), - null, Collections.emptyMap(), count ) ); + count, convertedFilteredCodes, filter, lastUpdatedDateRange ) ); } @Nonnull diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProvider.java index f582f41e..7b4e53df 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProvider.java @@ -28,11 +28,13 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; import org.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -57,10 +59,10 @@ public interface DhisToFhirDataProvider DhisResource findByDhisFhirIdentifier( @Nonnull FhirClient fhirClient, @Nonnull RuleInfo ruleInfo, @Nonnull String identifier ); @Nonnull - PreparedDhisToFhirSearch prepareSearchCasted( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) throws DhisToFhirDataProviderException; + PreparedDhisToFhirSearch prepareSearchCasted( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) throws DhisToFhirDataProviderException; @Nonnull - PreparedDhisToFhirSearch prepareSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) throws DhisToFhirDataProviderException; + PreparedDhisToFhirSearch prepareSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) throws DhisToFhirDataProviderException; @Nullable DhisToFhirSearchResult search( @Nonnull PreparedDhisToFhirSearch preparedSearch, @Nullable DhisToFhirSearchState state, int max ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProviderException.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProviderException.java index 06cc6f3b..111fca14 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProviderException.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirDataProviderException.java @@ -41,4 +41,9 @@ public DhisToFhirDataProviderException( String message ) { super( message ); } + + public DhisToFhirDataProviderException( String message, Throwable cause ) + { + super( message, cause ); + } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/PreparedDhisToFhirSearch.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/PreparedDhisToFhirSearch.java index a22a5fa2..cf7fe580 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/PreparedDhisToFhirSearch.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/PreparedDhisToFhirSearch.java @@ -28,6 +28,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; + +import javax.annotation.Nonnull; + /** * The prepared DHIS search. This is used for subsequent paged searches. * @@ -35,4 +39,6 @@ */ public interface PreparedDhisToFhirSearch { + @Nonnull + FhirVersion getFhirVersion(); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirDataProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirDataProvider.java index c1e004da..bf689f95 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirDataProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirDataProvider.java @@ -28,16 +28,23 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.metadata.model.ScriptVariable; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProvider; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; import org.dhis2.fhir.adapter.fhir.transform.dhis.PreparedDhisToFhirSearch; +import org.dhis2.fhir.adapter.fhir.transform.dhis.search.SearchFilter; +import org.dhis2.fhir.adapter.fhir.transform.dhis.search.SearchFilterCollector; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -50,9 +57,34 @@ */ public abstract class AbstractDhisToFhirDataProvider implements DhisToFhirDataProvider { + private final ScriptExecutor scriptExecutor; + + protected AbstractDhisToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor ) + { + this.scriptExecutor = scriptExecutor; + } + @Nonnull protected abstract Class getRuleClass(); + @Nonnull + protected SearchFilterCollector apply( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nonnull SearchFilterCollector searchFilterCollector ) + { + ruleInfos.forEach( ruleInfo -> { + if ( ruleInfo.getRule().getFilterScript() != null ) + { + final Boolean result = scriptExecutor.execute( ruleInfo.getRule().getFilterScript(), fhirVersion, + Collections.singletonMap( ScriptVariable.SEARCH_FILTER.getVariableName(), new SearchFilter( searchFilterCollector ) ), + Collections.emptyMap(), Boolean.class ); + if ( !Boolean.TRUE.equals( result ) ) + { + throw new DhisToFhirDataProviderException( "Search parameter filter could not be applied." ); + } + } + } ); + return searchFilterCollector; + } + @Nullable @Override public DhisResource findByDhisFhirIdentifierCasted( @Nonnull FhirClient fhirClient, @Nonnull RuleInfo ruleInfo, @Nonnull String identifier ) @@ -62,11 +94,11 @@ public DhisResource findByDhisFhirIdentifierCasted( @Nonnull FhirClient fhirClie @Nonnull @Override - public PreparedDhisToFhirSearch prepareSearchCasted( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) throws DhisToFhirDataProviderException + public PreparedDhisToFhirSearch prepareSearchCasted( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) throws DhisToFhirDataProviderException { final Class ruleClass = getRuleClass(); final List> castedRuleInfos = ruleInfos.stream().map( r -> new RuleInfo<>( getRuleClass().cast( r.getRule() ), r.getDhisDataReferences() ) ).collect( Collectors.toList() ); - return prepareSearch( castedRuleInfos, filter, count ); + return prepareSearch( fhirVersion, castedRuleInfos, filter, lastUpdatedDateRange, count ); } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractPreparedDhisToFhirSearch.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractPreparedDhisToFhirSearch.java index efd0ea67..8c4f8f9d 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractPreparedDhisToFhirSearch.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractPreparedDhisToFhirSearch.java @@ -28,11 +28,18 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; import org.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; import org.dhis2.fhir.adapter.fhir.transform.dhis.PreparedDhisToFhirSearch; +import org.dhis2.fhir.adapter.fhir.transform.dhis.search.SearchFilterCollector; +import org.springframework.web.util.UriBuilder; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.List; import java.util.Map; @@ -42,35 +49,75 @@ * @param the concrete type of the rule. * @author volsch */ -public abstract class AbstractPreparedDhisToFhirSearch implements PreparedDhisToFhirSearch +public abstract class AbstractPreparedDhisToFhirSearch implements PreparedDhisToFhirSearch, UriFilterApplier { + private final FhirVersion fhirVersion; + private final List> ruleInfos; - private final Map filter; + private final Map> filter; + + private final DateRangeParam lastUpdatedDateRange; private final int count; - protected AbstractPreparedDhisToFhirSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) + private UriFilterApplier uriFilterApplier; + + protected AbstractPreparedDhisToFhirSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) { + this.fhirVersion = fhirVersion; this.ruleInfos = ruleInfos; this.filter = filter; + this.lastUpdatedDateRange = lastUpdatedDateRange; this.count = count; } + @Nonnull + @Override + public FhirVersion getFhirVersion() + { + return fhirVersion; + } + @Nonnull public List> getRuleInfos() { return ruleInfos; } - @Nonnull - public Map getFilter() + @Nullable + public DateRangeParam getLastUpdatedDateRange() { - return filter; + return lastUpdatedDateRange; } public int getCount() { return count; } + + public void setUriFilterApplier( @Nonnull UriFilterApplier uriFilterApplier ) + { + this.uriFilterApplier = uriFilterApplier; + } + + public SearchFilterCollector createSearchFilterCollector() + { + return new SearchFilterCollector( filter ); + } + + @Nonnull + @Override + public U add( @Nonnull U uriBuilder, @Nonnull List variables ) + { + if ( uriFilterApplier == null ) + { + throw new IllegalStateException( "URI filter applier has not been set" ); + } + if ( ( lastUpdatedDateRange != null ) && !lastUpdatedDateRange.isEmpty() ) + { + throw new DhisToFhirDataProviderException( "Search parameter to filter last updated date range is not yet supported." ); + } + return uriFilterApplier.add( uriBuilder, variables ); + } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/OrganizationUnitToFhirDataProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/OrganizationUnitToFhirDataProvider.java index 45bba50c..3aaab04a 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/OrganizationUnitToFhirDataProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/OrganizationUnitToFhirDataProvider.java @@ -28,6 +28,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; +import org.dhis2.fhir.adapter.dhis.DhisFindException; import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; @@ -38,6 +40,8 @@ import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; import org.dhis2.fhir.adapter.fhir.metadata.model.OrganizationUnitRule; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProvider; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirSearchResult; @@ -61,8 +65,9 @@ public class OrganizationUnitToFhirDataProvider extends AbstractDhisToFhirDataPr { private final OrganizationUnitService organizationUnitService; - public OrganizationUnitToFhirDataProvider( @Nonnull OrganizationUnitService organizationUnitService ) + public OrganizationUnitToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor, @Nonnull OrganizationUnitService organizationUnitService ) { + super( scriptExecutor ); this.organizationUnitService = organizationUnitService; } @@ -89,15 +94,18 @@ public DhisResource findByDhisFhirIdentifier( @Nonnull FhirClient fhirClient, @N @Nonnull @Override - public PreparedDhisToFhirSearch prepareSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) throws DhisToFhirDataProviderException + public PreparedDhisToFhirSearch prepareSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) throws DhisToFhirDataProviderException { - return new PreparedOrganizationUnitDhisToFhirSearch( ruleInfos, filter, count ); + final PreparedOrganizationUnitDhisToFhirSearch ps = new PreparedOrganizationUnitDhisToFhirSearch( fhirVersion, ruleInfos, filter, lastUpdatedDateRange, count ); + ps.setUriFilterApplier( apply( fhirVersion, ruleInfos, ps.createSearchFilterCollector() ) ); + return ps; } @Nullable @Override public DhisToFhirSearchResult search( @Nonnull PreparedDhisToFhirSearch preparedSearch, @Nullable DhisToFhirSearchState state, int max ) { + final PreparedOrganizationUnitDhisToFhirSearch ps = (PreparedOrganizationUnitDhisToFhirSearch) preparedSearch; final OrganizationUnitToFhirSearchState ss = (OrganizationUnitToFhirSearchState) state; if ( (ss != null) && !ss.isMore() ) { @@ -105,7 +113,15 @@ public DhisToFhirSearchResult search( @Nonnull PreparedDhisToF } final int from = (ss == null) ? 0 : ss.getFrom(); - final DhisResourceResult result = organizationUnitService.find( from, max ); + final DhisResourceResult result; + try + { + result = organizationUnitService.find( ps, from, max ); + } + catch ( DhisFindException e ) + { + throw new DhisToFhirDataProviderException( e.getMessage(), e ); + } if ( result.getResources().isEmpty() ) { return null; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/PreparedOrganizationUnitDhisToFhirSearch.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/PreparedOrganizationUnitDhisToFhirSearch.java index 4ffa0f3f..768ef96f 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/PreparedOrganizationUnitDhisToFhirSearch.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/PreparedOrganizationUnitDhisToFhirSearch.java @@ -28,12 +28,15 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.model.OrganizationUnitRule; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import org.dhis2.fhir.adapter.fhir.transform.dhis.PreparedDhisToFhirSearch; import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.AbstractPreparedDhisToFhirSearch; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.List; import java.util.Map; @@ -44,8 +47,8 @@ */ public class PreparedOrganizationUnitDhisToFhirSearch extends AbstractPreparedDhisToFhirSearch { - public PreparedOrganizationUnitDhisToFhirSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) + public PreparedOrganizationUnitDhisToFhirSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) { - super( ruleInfos, filter, count ); + super( fhirVersion, ruleInfos, filter, lastUpdatedDateRange, count ); } } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/PreparedProgramStageToFhirSearch.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/PreparedProgramStageToFhirSearch.java index a95276be..35076aea 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/PreparedProgramStageToFhirSearch.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/PreparedProgramStageToFhirSearch.java @@ -28,9 +28,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramStageId; import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramStageRule; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import org.dhis2.fhir.adapter.fhir.transform.dhis.PreparedDhisToFhirSearch; import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.AbstractPreparedDhisToFhirSearch; @@ -48,9 +50,10 @@ public class PreparedProgramStageToFhirSearch extends AbstractPreparedDhisToFhir { private final List programStageIds; - public PreparedProgramStageToFhirSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count, @Nonnull List programStageIds ) + public PreparedProgramStageToFhirSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count, + @Nonnull List programStageIds ) { - super( ruleInfos, filter, count ); + super( fhirVersion, ruleInfos, filter, lastUpdatedDateRange, count ); this.programStageIds = programStageIds; } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirDataProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirDataProvider.java index f3200881..33435fae 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirDataProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirDataProvider.java @@ -28,6 +28,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; +import org.dhis2.fhir.adapter.dhis.DhisFindException; import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; @@ -41,6 +43,8 @@ import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramStageRule; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProvider; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; @@ -52,6 +56,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -71,8 +77,9 @@ public class ProgramStageToFhirDataProvider extends AbstractDhisToFhirDataProvid private final EventService eventService; - public ProgramStageToFhirDataProvider( @Nonnull ProgramMetadataService metadataService, @Nonnull EventService eventService ) + public ProgramStageToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor, @Nonnull ProgramMetadataService metadataService, @Nonnull EventService eventService ) { + super( scriptExecutor ); this.metadataService = metadataService; this.eventService = eventService; } @@ -101,20 +108,20 @@ public DhisResource findByDhisFhirIdentifier( @Nonnull FhirClient fhirClient, @N @Nonnull @Override - public PreparedDhisToFhirSearch prepareSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) throws DhisToFhirDataProviderException + public PreparedDhisToFhirSearch prepareSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) throws DhisToFhirDataProviderException { final Set refs = ruleInfos.stream() .filter( ri -> ri.getRule().getProgramStage().isEnabled() && ri.getRule().getProgramStage().isExpEnabled() && ri.getRule().getProgramStage().getProgram().isEnabled() && ri.getRule().getProgramStage().getProgram().isExpEnabled() ) .map( ri -> new ReferenceTuple( ri.getRule().getProgramStage().getProgram().getProgramReference(), ri.getRule().getProgramStage().getProgramStageReference() ) ) .collect( Collectors.toCollection( TreeSet::new ) ); - final List programStageIds = refs.stream().map( ref -> { + final Set programStageIds = refs.stream().map( ref -> { final Program program = metadataService.findProgramByReference( ref.getProgramReference() ) .orElseThrow( () -> new TransformerMappingException( "Program does not exist: " + ref.getProgramReference() ) ); final ProgramStage programStage = program.getOptionalStage( ref.getProgramStageReference() ) .orElseThrow( () -> new TransformerMappingException( "Program stage does not exist: " + ref.getProgramStageReference() ) ); return new ProgramStageId( program.getId(), programStage.getId() ); - } ).collect( Collectors.toList() ); - return new PreparedProgramStageToFhirSearch( ruleInfos, filter, count, programStageIds ); + } ).collect( Collectors.toCollection( LinkedHashSet::new ) ); + return new PreparedProgramStageToFhirSearch( fhirVersion, ruleInfos, filter, lastUpdatedDateRange, count, new ArrayList<>( programStageIds ) ); } @Nullable @@ -134,6 +141,9 @@ public DhisToFhirSearchResult search( @Nonnull PreparedD return null; } from = 0; + + // may be filtered by ID of program stage + ps.setUriFilterApplier( apply( ps.getFhirVersion(), ps.getRuleInfos(), ps.createSearchFilterCollector() ) ); } else { @@ -141,8 +151,16 @@ public DhisToFhirSearchResult search( @Nonnull PreparedD from = ss.getFrom(); } - final DhisResourceResult result = eventService.find( - programStageId.getProgramId(), programStageId.getProgramStageId(), from, max ); + final DhisResourceResult result; + try + { + result = eventService.find( + programStageId.getProgramId(), programStageId.getProgramStageId(), ps, from, max ); + } + catch ( DhisFindException e ) + { + throw new DhisToFhirDataProviderException( e.getMessage(), e ); + } return new DhisToFhirSearchResult<>( result.getResources(), new ProgramStageToFhirSearchState( programStageId, from + result.getResources().size(), !result.getResources().isEmpty() && result.isMore() ) ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirTransformer.java index eea23bf0..6a7db224 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/program/ProgramStageToFhirTransformer.java @@ -264,7 +264,7 @@ private DhisToFhirTransformOutcome handleDataDelete( @N private DhisToFhirTransformOutcome createResult( @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo ruleInfo, @Nonnull Map variables, @Nonnull IBaseResource resource, @Nonnull IBaseResource modifiedResource ) { - if ( evaluateNotModified( context, variables, resource, modifiedResource ) ) + if ( !context.getDhisRequest().isDhisFhirId() && evaluateNotModified( context, variables, resource, modifiedResource ) ) { // resource has not been changed and do not need to be updated return new DhisToFhirTransformOutcome<>( ruleInfo.getRule(), null ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/PreparedTrackedEntityToFhirSearch.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/PreparedTrackedEntityToFhirSearch.java index 76f12e25..278a6bb4 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/PreparedTrackedEntityToFhirSearch.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/PreparedTrackedEntityToFhirSearch.java @@ -28,8 +28,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; import org.dhis2.fhir.adapter.fhir.metadata.model.TrackedEntityRule; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import org.dhis2.fhir.adapter.fhir.transform.dhis.PreparedDhisToFhirSearch; import org.dhis2.fhir.adapter.fhir.transform.dhis.impl.AbstractPreparedDhisToFhirSearch; @@ -47,9 +49,10 @@ public class PreparedTrackedEntityToFhirSearch extends AbstractPreparedDhisToFhi { private final List typeIds; - public PreparedTrackedEntityToFhirSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count, @Nonnull List typeIds ) + public PreparedTrackedEntityToFhirSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count, + @Nonnull List typeIds ) { - super( ruleInfos, filter, count ); + super( fhirVersion, ruleInfos, filter, lastUpdatedDateRange, count ); this.typeIds = typeIds; } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/TrackedEntityToFhirDataProvider.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/TrackedEntityToFhirDataProvider.java index 81b55abe..6b5d754a 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/TrackedEntityToFhirDataProvider.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/trackedentity/TrackedEntityToFhirDataProvider.java @@ -28,6 +28,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import ca.uhn.fhir.rest.param.DateRangeParam; +import org.dhis2.fhir.adapter.dhis.DhisFindException; import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.dhis.model.DhisResourceResult; import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; @@ -41,6 +43,8 @@ import org.dhis2.fhir.adapter.fhir.metadata.model.FhirClient; import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo; import org.dhis2.fhir.adapter.fhir.metadata.model.TrackedEntityRule; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProvider; import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; @@ -72,8 +76,9 @@ public class TrackedEntityToFhirDataProvider extends AbstractDhisToFhirDataProvi private final TrackedEntityService service; - public TrackedEntityToFhirDataProvider( @Nonnull TrackedEntityMetadataService metadataService, @Nonnull TrackedEntityService service ) + public TrackedEntityToFhirDataProvider( @Nonnull ScriptExecutor scriptExecutor, @Nonnull TrackedEntityMetadataService metadataService, @Nonnull TrackedEntityService service ) { + super( scriptExecutor ); this.metadataService = metadataService; this.service = service; } @@ -112,13 +117,13 @@ public DhisResource findByDhisFhirIdentifier( @Nonnull FhirClient fhirClient, @N @Nonnull @Override - public PreparedDhisToFhirSearch prepareSearch( @Nonnull List> ruleInfos, @Nonnull Map filter, int count ) throws DhisToFhirDataProviderException + public PreparedDhisToFhirSearch prepareSearch( @Nonnull FhirVersion fhirVersion, @Nonnull List> ruleInfos, @Nullable Map> filter, @Nullable DateRangeParam lastUpdatedDateRange, int count ) throws DhisToFhirDataProviderException { final Set typeRefs = ruleInfos.stream().filter( ri -> ri.getRule().getTrackedEntity().isEnabled() && ri.getRule().getTrackedEntity().isExpEnabled() ) .map( ri -> ri.getRule().getTrackedEntity().getTrackedEntityReference() ).collect( Collectors.toCollection( TreeSet::new ) ); final List trackedEntityTypes = typeRefs.stream().map( typeRef -> metadataService.findTypeByReference( typeRef ) .orElseThrow( () -> new TransformerMappingException( "Tracked entity type does not exist: " + typeRef ) ) ).collect( Collectors.toList() ); - return new PreparedTrackedEntityToFhirSearch( ruleInfos, filter, count, trackedEntityTypes.stream().map( Identifiable::getId ).collect( Collectors.toList() ) ); + return new PreparedTrackedEntityToFhirSearch( fhirVersion, ruleInfos, filter, lastUpdatedDateRange, count, trackedEntityTypes.stream().map( Identifiable::getId ).collect( Collectors.toList() ) ); } @Nullable @@ -138,6 +143,9 @@ public DhisToFhirSearchResult search( @Nonnull PreparedD return null; } from = 0; + + // may be filtered by ID of tracked entity type + ps.setUriFilterApplier( apply( ps.getFhirVersion(), ps.getRuleInfos(), ps.createSearchFilterCollector() ) ); } else { @@ -145,7 +153,15 @@ public DhisToFhirSearchResult search( @Nonnull PreparedD from = ss.getFrom(); } - final DhisResourceResult result = service.find( typeId, from, max ); + final DhisResourceResult result; + try + { + result = service.find( typeId, ps, from, max ); + } + catch ( DhisFindException e ) + { + throw new DhisToFhirDataProviderException( e.getMessage(), e ); + } return new DhisToFhirSearchResult<>( result.getResources(), new TrackedEntityToFhirSearchState( typeId, from + result.getResources().size(), !result.getResources().isEmpty() && result.isMore() ) ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/PrefixedSearchValue.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/PrefixedSearchValue.java new file mode 100644 index 00000000..2481d7a6 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/PrefixedSearchValue.java @@ -0,0 +1,103 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.search; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Contains a prefixed search value. + * + * @author volsch + */ +public class PrefixedSearchValue implements Serializable +{ + private static final long serialVersionUID = 4349754861599731473L; + + private static final Pattern PREFIX_PATTERN = Pattern.compile( "([a-z]+)(\\d.*)" ); + + public static final String EQ_PREFIX = "eq"; + + public static final String NE_PREFIX = "ne"; + + public static final String GT_PREFIX = "gt"; + + public static final String LT_PREFIX = "lt"; + + public static final String GE_PREFIX = "ge"; + + public static final String LE_PREFIX = "le"; + + private final String prefix; + + private final String value; + + public PrefixedSearchValue( @Nullable String prefixedValue, boolean prefixAllowed ) + { + if ( prefixAllowed && ( prefixedValue != null ) ) + { + final Matcher matcher = PREFIX_PATTERN.matcher( prefixedValue ); + if ( matcher.matches() ) + { + this.prefix = matcher.group( 1 ); + this.value = matcher.group( 2 ); + } + else + { + this.prefix = null; + this.value = prefixedValue; + } + } + else + { + this.prefix = null; + this.value = prefixedValue; + } + } + + @Nullable + public String getPrefix() + { + return prefix; + } + + @Nullable + public String getValue() + { + return value; + } + + @Override + public String toString() + { + return "PrefixedSearchValue{" + "prefix='" + prefix + '\'' + ", value='" + value + '\'' + '}'; + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilter.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilter.java new file mode 100644 index 00000000..e692613c --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilter.java @@ -0,0 +1,252 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.search; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.apache.commons.lang3.StringUtils; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceType; +import org.dhis2.fhir.adapter.fhir.repository.DhisFhirResourceId; +import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; +import org.dhis2.fhir.adapter.scriptable.Scriptable; +import org.dhis2.fhir.adapter.util.NameUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * A generic search filter that prepares the URL filter values + * of requests to DHIS 2. + * + * @author volsch + */ +@Scriptable +public class SearchFilter +{ + private final SearchFilterCollector searchFilterCollector; + + public SearchFilter( @Nonnull SearchFilterCollector searchFilterCollector ) + { + this.searchFilterCollector = searchFilterCollector; + } + + public boolean addReference( @Nonnull String fhirSearchParamName, @Nullable Object defaultFhirResourceType, @Nonnull Object dhisResourceType, @Nonnull Object dhisProperty ) + { + final String dhisPropertyName = searchFilterCollector.mapDhisProperty( dhisProperty ); + final FhirResourceType fhirType = resolveFhirResourceType( defaultFhirResourceType ); + final DhisResourceType dhisType = resolveDhisResourceType( dhisResourceType ); + + final List searchParamValues = searchFilterCollector.processSearchParamValues( fhirSearchParamName ); + if ( searchParamValues == null ) + { + return false; + } + + if ( searchParamValues.size() != 1 ) + { + throw new DhisToFhirDataProviderException( "Multiple FHIR resource references are not supported for filtering: " + fhirSearchParamName ); + } + final SearchParamValue spv = searchParamValues.get( 0 ); + if ( spv.getModifier() != null ) + { + throw new DhisToFhirDataProviderException( "Modifiers are not supported for filtering with FHIR resource references: " + fhirSearchParamName ); + } + if ( spv.getValues().size() != 1 ) + { + throw new DhisToFhirDataProviderException( "Multiple FHIR resource references are not supported for filtering: " + fhirSearchParamName ); + } + + final DhisFhirResourceId dhisFhirResourceId = extractDhisFhirResourceId( spv.getValues().get( 0 ) ); + if ( !dhisFhirResourceId.getType().equals( dhisType ) ) + { + throw new DhisToFhirDataProviderException( "Search filter contains unexpected FHIR resource reference: " + dhisFhirResourceId ); + } + + if ( SearchFilterCollector.QUERY_PARAM_NAMES.contains( dhisPropertyName ) ) + { + searchFilterCollector.addQueryParam( dhisPropertyName, dhisFhirResourceId.getId() ); + } + else + { + searchFilterCollector.addFilterExpression( dhisPropertyName, "eq", dhisFhirResourceId.getId() ); + } + return true; + } + + public boolean addToken( @Nonnull String fhirSearchParamName, @Nonnull String searchParamValue, @Nonnull Object dhisProperty, @Nonnull String dhisOperator, @Nullable String dhisValue ) + { + final String dhisPropertyName = searchFilterCollector.mapDhisProperty( dhisProperty ); + + final List searchParamValues = searchFilterCollector.processSearchParamValues( fhirSearchParamName ); + if ( ( searchParamValues == null ) || ( searchParamValues.size() != 1 ) ) + { + return false; + } + final SearchParamValue spv = searchParamValues.get( 0 ); + if ( spv.getModifier() != null ) + { + throw new DhisToFhirDataProviderException( "Modifiers are not supported for filtering tokens: " + fhirSearchParamName ); + } + if ( ( spv.getValues().size() != 1 ) || !searchParamValue.equals( spv.getValues().get( 0 ) ) ) + { + return false; + } + + searchFilterCollector.addFilterExpression( dhisPropertyName, dhisOperator, StringUtils.defaultString( dhisValue ) ); + return true; + } + + public boolean add( @Nonnull String fhirSearchParamName, @Nonnull Object searchParamType, @Nonnull Object dhisProperty ) + { + final String dhisPropertyName = searchFilterCollector.mapDhisProperty( dhisProperty ); + final SearchParamType type = resolveSearchParamType( searchParamType ); + + final List searchParamValue = searchFilterCollector.processSearchParamValues( fhirSearchParamName ); + if ( searchParamValue == null ) + { + return false; + } + + searchParamValue.forEach( spv -> { + spv.validate( type ); + + String dhisOperator = ( type == SearchParamType.STRING ) ? "$ilike" : "eq"; + if ( spv.getModifier() != null ) + { + switch ( spv.getModifier() ) + { + case SearchParamValue.EXACT_MODIFIER: + dhisOperator = "eq"; + break; + case SearchParamValue.CONTAINS_MODIFIER: + dhisOperator = "ilike"; + break; + default: + throw new DhisToFhirDataProviderException( "Unsupported search modifier: " + spv.getModifier() ); + } + } + + for ( final PrefixedSearchValue psv : spv.getPrefixedValue( type.isPrefixAllowed() ) ) + { + if ( psv.getPrefix() != null ) + { + switch ( psv.getPrefix() ) + { + case PrefixedSearchValue.EQ_PREFIX: + dhisOperator = "eq"; + break; + case PrefixedSearchValue.NE_PREFIX: + dhisOperator = "ne"; + break; + case PrefixedSearchValue.LT_PREFIX: + dhisOperator = "lt"; + break; + case PrefixedSearchValue.GT_PREFIX: + dhisOperator = "gt"; + break; + case PrefixedSearchValue.LE_PREFIX: + dhisOperator = "le"; + break; + case PrefixedSearchValue.GE_PREFIX: + dhisOperator = "ge"; + break; + default: + throw new DhisToFhirDataProviderException( "Unsupported search prefix: " + psv.getPrefix() ); + } + } + searchFilterCollector.addFilterExpression( dhisPropertyName, dhisOperator, + type.convertToDhis( StringUtils.defaultString( psv.getValue() ) ) ); + } + } ); + return true; + } + + @Nonnull + protected SearchParamType resolveSearchParamType( @Nonnull Object searchParamType ) + { + try + { + return NameUtils.toEnumValue( SearchParamType.class, searchParamType ); + } + catch ( IllegalArgumentException e ) + { + throw new TransformerMappingException( "Invalid search parameter type: " + searchParamType ); + } + } + + @Nullable + protected FhirResourceType resolveFhirResourceType( @Nullable Object fhirResourceType ) + { + try + { + return NameUtils.toEnumValue( FhirResourceType.class, fhirResourceType ); + } + catch ( IllegalArgumentException e ) + { + throw new TransformerMappingException( "Invalid FHIR resource typè: " + fhirResourceType ); + } + } + + @Nonnull + protected DhisResourceType resolveDhisResourceType( @Nonnull Object dhisResourceType ) + { + try + { + return NameUtils.toEnumValue( DhisResourceType.class, dhisResourceType ); + } + catch ( IllegalArgumentException e ) + { + throw new TransformerMappingException( "Invalid DHIS resource typè: " + dhisResourceType ); + } + } + + @Nonnull + protected DhisFhirResourceId extractDhisFhirResourceId( @Nonnull String value ) + { + final String resultingValue; + final int index = value.lastIndexOf( '/' ); + if ( index >= 0 ) + { + resultingValue = value.substring( index + 1 ); + } + else + { + resultingValue = value; + } + try + { + return DhisFhirResourceId.parse( resultingValue ); + } + catch ( IllegalArgumentException e ) + { + throw new DhisToFhirDataProviderException( "Search filter contains invalid DHIS FHIR resource ID: " + value ); + } + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilterCollector.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilterCollector.java new file mode 100644 index 00000000..b2fcc176 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchFilterCollector.java @@ -0,0 +1,138 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.search; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.apache.commons.lang3.StringUtils; +import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.dhis.model.UriFilterApplier; +import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; +import org.springframework.web.util.UriBuilder; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +/** + * Collects the search filter in order to add the values to an URI builder. + * + * @author volsch + */ +public class SearchFilterCollector implements UriFilterApplier +{ + public static final Set QUERY_PARAM_NAMES = Collections.unmodifiableSet( + new HashSet<>( Arrays.asList( "orgUnit", "trackedEntityInstance", "event" ) ) ); + + private final Function dhisPropertyRefResolver; + + private final Map> filter = new HashMap<>(); + + private final Map> queryParams = new HashMap<>(); + + private final Set filterExpressions = new HashSet<>(); + + public SearchFilterCollector( @Nullable Map> filter ) + { + this( null, filter ); + } + + public SearchFilterCollector( @Nullable Function dhisPropertyRefResolver, @Nullable Map> filter ) + { + this.dhisPropertyRefResolver = dhisPropertyRefResolver; + if ( filter != null ) + { + filter.forEach( ( key, value ) -> { + final SearchParamValue spv = new SearchParamValue( key, value ); + this.filter.computeIfAbsent( spv.getName(), ( k ) -> new ArrayList<>() ).add( spv ); + } ); + } + } + + @Nullable + public List processSearchParamValues( @Nonnull String searchParamName ) + { + return filter.remove( searchParamName ); + } + + @Nonnull + public String mapDhisProperty( @Nonnull Object property ) + { + if ( property instanceof String ) + { + return (String) property; + } + if ( property instanceof Reference ) + { + if ( dhisPropertyRefResolver == null ) + { + throw new TransformerMappingException( "Mapping reference search properties is not supported: " + property ); + } + return dhisPropertyRefResolver.apply( (Reference) property ); + } + throw new TransformerMappingException( "Not a valid search property type: " + property.getClass() ); + } + + public void addQueryParam( @Nonnull String propertyName, @Nullable String value ) + { + queryParams.put( propertyName, Collections.singletonList( StringUtils.defaultString( value ) ) ); + } + + public void addFilterExpression( @Nonnull String propertyName, @Nonnull String operator, @Nullable String value ) + { + if ( ( value != null ) && ( value.indexOf( ':' ) >= 0 ) ) + { + throw new DhisToFhirDataProviderException( "Colon characters in search parameter values are not supported." ); + } + filterExpressions.add( propertyName + ':' + operator + ':' + StringUtils.defaultString( value ) ); + } + + @Override + @Nonnull + public U add( @Nonnull U uriBuilder, @Nonnull List variables ) throws DhisToFhirDataProviderException + { + if ( !filter.isEmpty() ) + { + throw new DhisToFhirDataProviderException( "Unhandled search parameters: " + StringUtils.join( filter.keySet(), ", " ) ); + } + queryParams.forEach( ( key, values ) -> uriBuilder.queryParam( key, values.toArray() ) ); + filterExpressions.forEach( fe -> { + uriBuilder.queryParam( "filter", "{sfc" + variables.size() + "}" ); + variables.add( fe ); + } ); + return uriBuilder; + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchParamType.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchParamType.java new file mode 100644 index 00000000..bbca1d6d --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchParamType.java @@ -0,0 +1,138 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.search; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ca.uhn.fhir.model.api.TemporalPrecisionEnum; +import ca.uhn.fhir.model.primitive.DateTimeDt; +import ca.uhn.fhir.parser.DataFormatException; +import org.dhis2.fhir.adapter.converter.DateToIsoDateStringConverter; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; + +import javax.annotation.Nullable; +import java.util.regex.Pattern; + +/** + * Specifies the different types of FHIR search parameters. + * + * @author volsch + */ +public enum SearchParamType +{ + NUMBER( false, true ) + { + private final Pattern NUMBER_PATTERN = Pattern.compile( "\\d+(\\.\\d+)([eE]\\d{1,2})?" ); + + @Nullable + @Override + public String convertToDhis( @Nullable String value ) throws DhisToFhirDataProviderException + { + if ( ( value != null ) && !NUMBER_PATTERN.matcher( value ).matches() ) + { + throw new DhisToFhirDataProviderException( "Search parameter value is not a number: " + value ); + } + return value; + } + }, + DATE( false, true ) + { + private final DateToIsoDateStringConverter converter = new DateToIsoDateStringConverter(); + + @Nullable + @Override + public String convertToDhis( @Nullable String value ) throws DhisToFhirDataProviderException + { + if ( value == null ) + { + return null; + } + try + { + final DateTimeDt dateTimeDt = new DateTimeDt(); + dateTimeDt.setPrecision( TemporalPrecisionEnum.MILLI ); + dateTimeDt.setValueAsString( value ); + return converter.doConvert( dateTimeDt.getValue() ); + } + catch ( DataFormatException e ) + { + throw new DhisToFhirDataProviderException( "Search parameter is not a valid date: " + value ); + } + } + }, + STRING( true, false ) + { + @Nullable + @Override + public String convertToDhis( @Nullable String value ) throws DhisToFhirDataProviderException + { + return value; + } + }, + REFERENCE( false, false ) + { + @Nullable + @Override + public String convertToDhis( @Nullable String value ) throws DhisToFhirDataProviderException + { + throw new IllegalStateException( "Reference values cannot be converted to DHIS" ); + } + }, + TOKEN( true, false ) + { + @Nullable + @Override + public String convertToDhis( @Nullable String value ) throws DhisToFhirDataProviderException + { + return value; + } + }; + + private final boolean modifierAllowed; + + private final boolean prefixAllowed; + + SearchParamType( boolean modifierAllowed, boolean prefixAllowed ) + { + this.modifierAllowed = modifierAllowed; + this.prefixAllowed = prefixAllowed; + } + + public boolean isModifierAllowed() + { + return modifierAllowed; + } + + public boolean isPrefixAllowed() + { + return prefixAllowed; + } + + @Nullable + public abstract String convertToDhis( @Nullable String value ) + throws DhisToFhirDataProviderException; +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchParamValue.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchParamValue.java new file mode 100644 index 00000000..cf5815e5 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/search/SearchParamValue.java @@ -0,0 +1,146 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.search; + +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import org.apache.commons.lang.StringUtils; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * Search param value that may contain a modifier (the part behind the colon that + * is specified after the search parameter). + * + * @author volsch + */ +public class SearchParamValue implements Serializable +{ + private static final long serialVersionUID = -5201031184095992009L; + + public static final String EXACT_MODIFIER = "exact"; + + public static final String CONTAINS_MODIFIER = "contains"; + + private final String name; + + private final String modifier; + + private final List values; + + public SearchParamValue( @Nonnull String name, @Nonnull List values ) + { + final int modifierIndex = name.lastIndexOf( ':' ); + if ( modifierIndex > 0 ) + { + this.name = name.substring( 0, modifierIndex ); + this.modifier = StringUtils.defaultIfBlank( name.substring( modifierIndex + 1 ), null ); + } + else + { + this.name = name; + this.modifier = null; + } + this.values = values; + } + + @Nonnull + public String getName() + { + return name; + } + + @Nullable + public String getModifier() + { + return modifier; + } + + @Nonnull + public List getValues() + { + return values; + } + + @Nonnull + public List getPrefixedValue( boolean prefixAllowed ) + { + final List result = new ArrayList<>(); + getValues().forEach( v -> result.add( new PrefixedSearchValue( v, prefixAllowed ) ) ); + return result; + } + + public void validate( @Nonnull SearchParamType searchParamType ) throws DhisToFhirDataProviderException + { + if ( modifier != null ) + { + switch ( modifier ) + { + case EXACT_MODIFIER: + case CONTAINS_MODIFIER: + if ( searchParamType != SearchParamType.STRING ) + { + throw new DhisToFhirDataProviderException( "Search parameter type " + searchParamType + " does not support modifier: " + modifier ); + } + break; + default: + throw new DhisToFhirDataProviderException( "Unsupported search modifier: " + modifier ); + } + } + if ( searchParamType.isPrefixAllowed() ) + { + getPrefixedValue( true ).forEach( pv -> { + if ( pv.getPrefix() != null ) + { + switch ( pv.getPrefix() ) + { + case PrefixedSearchValue.EQ_PREFIX: + case PrefixedSearchValue.NE_PREFIX: + case PrefixedSearchValue.LT_PREFIX: + case PrefixedSearchValue.GT_PREFIX: + case PrefixedSearchValue.LE_PREFIX: + case PrefixedSearchValue.GE_PREFIX: + break; + default: + throw new DhisToFhirDataProviderException( "Unsupported search prefix: " + pv.getPrefix() ); + } + } + } ); + } + } + + @Override + public String toString() + { + return "SearchParamValue{" + "name='" + name + '\'' + ", modifier='" + modifier + '\'' + ", values=" + values + '}'; + } +} diff --git a/fhir/src/main/resources/db/migration/production/V1.1.0.18_0_0__Search_Filter.sql b/fhir/src/main/resources/db/migration/production/V1.1.0.18_0_0__Search_Filter.sql new file mode 100644 index 00000000..e9f1ad30 --- /dev/null +++ b/fhir/src/main/resources/db/migration/production/V1.1.0.18_0_0__Search_Filter.sql @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004-2019, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO PROGRAM_STAGE_EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +-- @formatter:off + +INSERT INTO fhir_script_variable_enum VALUES ('SEARCH_FILTER'); +INSERT INTO fhir_script_type_enum VALUES ('SEARCH_FILTER'); + +ALTER TABLE fhir_rule + ADD filter_script_id UUID, + ADD CONSTRAINT fhir_rule_fk8 FOREIGN KEY (filter_script_id) REFERENCES fhir_executable_script(id); +CREATE INDEX fhir_rule_i7 ON fhir_rule(filter_script_id); + +INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type) +VALUES ('cf3072ec-06ad-4d62-a8a0-75ad2ab330ba', 0, 'SEARCH_FILTER_LOCATION', 'Prepares Location Search Filter', 'Prepares Location Search Filter.', 'SEARCH_FILTER', 'BOOLEAN'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('cf3072ec-06ad-4d62-a8a0-75ad2ab330ba', 'SEARCH_FILTER'); +INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) +VALUES ('10200cc2-f060-4aa8-a907-0d12b199ff3b', 0, 'cf3072ec-06ad-4d62-a8a0-75ad2ab330ba', +'searchFilter.add(''name'', ''string'', ''name''); +searchFilter.addReference(''part-of'', ''location'', ''organization-unit'', ''parent''); +searchFilter.addToken(''status'', ''active'', ''closedDate'', ''null'', null); +searchFilter.addToken(''status'', ''inactive'', ''closedDate'', ''!null'', null); +true', 'JAVASCRIPT'); +INSERT INTO fhir_script_source_version (script_source_id, fhir_version) +VALUES ('10200cc2-f060-4aa8-a907-0d12b199ff3b', 'DSTU3'); +INSERT INTO fhir_script_source_version (script_source_id, fhir_version) +VALUES ('10200cc2-f060-4aa8-a907-0d12b199ff3b', 'R4'); +INSERT INTO fhir_executable_script (id, version, script_id, name, code) +VALUES ('27f50aeb-0f56-4256-ae16-6118e931524b', 0, 'cf3072ec-06ad-4d62-a8a0-75ad2ab330ba', 'Prepares Location Search Filter', 'SEARCH_FILTER_LOCATION'); +UPDATE fhir_rule SET filter_script_id='27f50aeb-0f56-4256-ae16-6118e931524b' WHERE id='b9546b02-4adc-4868-a4cd-d5d7789f0df0'; + +INSERT INTO fhir_script (id, version, code, name, description, script_type, return_type) +VALUES ('e85a46b3-279a-4c1f-ab34-b73109a3addb', 0, 'SEARCH_FILTER_ORGANIZATION', 'Prepares Organization Search Filter', 'Prepares Organization Search Filter.', 'SEARCH_FILTER', 'BOOLEAN'); +INSERT INTO fhir_script_variable (script_id, variable) VALUES ('e85a46b3-279a-4c1f-ab34-b73109a3addb', 'SEARCH_FILTER'); +INSERT INTO fhir_script_source (id, version, script_id, source_text, source_type) +VALUES ('1f1f0ce9-5b9b-4ce1-b882-4e40713314bf', 0, 'e85a46b3-279a-4c1f-ab34-b73109a3addb', +'searchFilter.add(''name'', ''string'', ''name''); +searchFilter.addReference(''part-of'', ''organization'', ''organization-unit'', ''parent''); +searchFilter.addToken(''status'', ''true'', ''closedDate'', ''null'', null); +searchFilter.addToken(''status'', ''false'', ''closedDate'', ''!null'', null); +true', 'JAVASCRIPT'); +INSERT INTO fhir_script_source_version (script_source_id, fhir_version) +VALUES ('1f1f0ce9-5b9b-4ce1-b882-4e40713314bf', 'DSTU3'); +INSERT INTO fhir_script_source_version (script_source_id, fhir_version) +VALUES ('1f1f0ce9-5b9b-4ce1-b882-4e40713314bf', 'R4'); +INSERT INTO fhir_executable_script (id, version, script_id, name, code) +VALUES ('21567ae5-610c-4883-bf2d-9b439040ef2d', 0, 'e85a46b3-279a-4c1f-ab34-b73109a3addb', 'Prepares Organization Search Filter', 'SEARCH_FILTER_ORGANIZATION'); +UPDATE fhir_rule SET filter_script_id='21567ae5-610c-4883-bf2d-9b439040ef2d' WHERE id='d0e1472a-05e6-47c9-b36b-ff1f06fec352'; + diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/OrganizationUnitRuleRepositoryRestDocsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/OrganizationUnitRuleRepositoryRestDocsTest.java index 6c31a8d3..51c323f7 100644 --- a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/OrganizationUnitRuleRepositoryRestDocsTest.java +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/OrganizationUnitRuleRepositoryRestDocsTest.java @@ -108,7 +108,8 @@ public void createOrganizationUnitRule() throws Exception .type( JsonFieldType.STRING ), fields.withPath( "managingOrgIdentifierLookupScript" ).description( "Link to the executable script reference that is used to extract the managing organization unit identifier from the DHIS 2 organization unit. The script must be an evaluation script that returns a STRING." ) - .type( JsonFieldType.STRING ).optional() + .type( JsonFieldType.STRING ).optional(), + fields.withPath( "filterScript" ).description( "Link to the executable script that prepares the search filter." ).type( JsonFieldType.STRING ).optional() ) ) ).andReturn().getResponse().getHeader( "Location" ); mockMvc @@ -138,6 +139,7 @@ public void readOrganizationUnitRule() throws Exception .andDo( documentationHandler.document( links( linkWithRel( "self" ).description( "Link to this resource itself." ), linkWithRel( "organizationUnitRule" ).description( "Link to this resource itself." ), + linkWithRel( "filterScript" ).description( "Link to the executable script that prepares the search filter." ).optional(), linkWithRel( "applicableCodeSet" ).description( "Link to the code set reference that is used to check if the incoming request is applicable for this rule." ).optional(), linkWithRel( "applicableImpScript" ).description( "Link to the executable script reference that is used to check if the incoming request is applicable for this rule. The script must be an evaluation script that returns a boolean value." ) .optional(), diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/ProgramStageRuleRepositoryRestDocsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/ProgramStageRuleRepositoryRestDocsTest.java index 6983d04f..07c259c5 100644 --- a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/ProgramStageRuleRepositoryRestDocsTest.java +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/ProgramStageRuleRepositoryRestDocsTest.java @@ -142,7 +142,8 @@ public void createProgramStageRule() throws Exception .type( JsonFieldType.STRING ).optional(), fields.withPath( "programStage" ).description( "Link to the tracked entity resource that describes the tracked entity of the transformation." ).type( JsonFieldType.STRING ), fields.withPath( "expDeleteEvaluateScript" ).description( "Link to the executable evaluation script that evaluates if the transformation should result in a deletion of the corresponding FHIR resource." ) - .type( JsonFieldType.STRING ).optional() ) + .type( JsonFieldType.STRING ).optional(), + fields.withPath( "filterScript" ).description( "Link to the executable script that prepares the search filter." ).type( JsonFieldType.STRING ).optional() ) ) ).andReturn().getResponse().getHeader( "Location" ); mockMvc @@ -172,6 +173,7 @@ public void readProgramStageRule() throws Exception .andDo( documentationHandler.document( links( linkWithRel( "self" ).description( "Link to this resource itself." ), linkWithRel( "programStageRule" ).description( "Link to this resource itself." ), + linkWithRel( "filterScript" ).description( "Link to the executable script that prepares the search filter." ).optional(), linkWithRel( "applicableCodeSet" ).description( "Link to the code set reference that is used to check if the incoming request is applicable for this rule." ).optional(), linkWithRel( "applicableImpScript" ).description( "Link to the executable script reference that is used to check if the incoming request is applicable for this rule. The script must be an evaluation script that returns a boolean value." ).optional(), linkWithRel( "transformImpScript" ).description( "Link to the executable script reference that is used to transform the FHIR resource input to the DHIS2 resource." ).optional(), diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/TrackedEntityRuleRepositoryRestDocsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/TrackedEntityRuleRepositoryRestDocsTest.java index 00cae6fc..2db1c6cf 100644 --- a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/TrackedEntityRuleRepositoryRestDocsTest.java +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/TrackedEntityRuleRepositoryRestDocsTest.java @@ -119,7 +119,8 @@ public void createTrackedEntityRule() throws Exception fields.withPath( "expGeoTransformScript" ).description( "Link to the executable transformation script that performs the transformation of the GEO coordinates that are included in the tracked entity instance." ) .type( JsonFieldType.STRING ).optional(), fields.withPath( "expOuTransformScript" ).description( "Link to the executable transformation script that performs the transformation of the DHIS organization unit to a FHIR resource (e.g. FHIR organization or location)." ) - .type( JsonFieldType.STRING ).optional() + .type( JsonFieldType.STRING ).optional(), + fields.withPath( "filterScript" ).description( "Link to the executable script that prepares the search filter." ).type( JsonFieldType.STRING ).optional() ) ) ).andReturn().getResponse().getHeader( "Location" ); mockMvc @@ -149,6 +150,7 @@ public void readTrackedEntityRule() throws Exception .andDo( documentationHandler.document( links( linkWithRel( "self" ).description( "Link to this resource itself." ), linkWithRel( "trackedEntityRule" ).description( "Link to this resource itself." ), + linkWithRel( "filterScript" ).description( "Link to the executable script that prepares the search filter." ).optional(), linkWithRel( "applicableCodeSet" ).description( "Link to the code set reference that is used to check if the incoming request is applicable for this rule." ).optional(), linkWithRel( "applicableImpScript" ).description( "Link to the executable script reference that is used to check if the incoming request is applicable for this rule. The script must be an evaluation script that returns a boolean value." ).optional(), linkWithRel( "transformImpScript" ).description( "Link to the executable script reference that is used to transform the FHIR resource input to the DHIS2 resource." ).optional(),