From faeab2ce56d76af50ec477564dd9036c8f92ef13 Mon Sep 17 00:00:00 2001 From: Volker Schmidt Date: Tue, 13 Aug 2019 16:09:21 +0200 Subject: [PATCH] Added support for multiple transformers for one resource type. Tests are still missing. --- .../impl/AbstractDhisToFhirTransformer.java | 21 ++++++- .../dhis/impl/DhisToFhirTransformer.java | 7 ++- .../DhisToFhirTransformerServiceImpl.java | 52 ++++++++++------ .../OrganizationUnitToFhirTransformer.java | 1 + .../impl/AbstractFhirToDhisTransformer.java | 21 ++++++- .../fhir/impl/FhirToDhisTransformer.java | 7 ++- .../FhirToDhisTransformerServiceImpl.java | 61 ++++++++++++------- 7 files changed, 126 insertions(+), 44 deletions(-) diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java index f627f364..32653111 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/AbstractDhisToFhirTransformer.java @@ -74,7 +74,7 @@ import java.util.Optional; /** - * Transforms a DHIS2 resource to a FHIR resource. + * Transforms a DHIS2 resource to a FHIR resource. The default priority of the transformer is 0. * * @param the concrete type of the DHIS2 resource that is processed by this transformer. * @param the concrete type of the transformer rule that is processed by this transformer. @@ -105,6 +105,25 @@ public AbstractDhisToFhirTransformer( @Nonnull ScriptExecutor scriptExecutor, @N this.fhirDhisAssignmentRepository = fhirDhisAssignmentRepository; } + @Override + public int getPriority() + { + return 0; + } + + @Override + public int compareTo( @Nonnull DhisToFhirTransformer o ) + { + final int value = getPriority() - o.getPriority(); + + if ( value != 0 ) + { + return value; + } + + return getClass().getSimpleName().compareTo( o.getClass().getSimpleName() ); + } + @Nonnull protected LockManager getLockManager() { diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformer.java index ae5737a8..ec8131a3 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformer.java @@ -50,7 +50,7 @@ * @param the concrete type of the transformer rule that is processed by this transformer. * @author volsch */ -public interface DhisToFhirTransformer extends FhirVersionRestricted +public interface DhisToFhirTransformer extends FhirVersionRestricted, Comparable> { @Nonnull DhisResourceType getDhisResourceType(); @@ -61,6 +61,11 @@ public interface DhisToFhirTransformer getRuleClass(); + /** + * @return the priority of this transformer (matching transformers with a higher priority are used first). + */ + int getPriority(); + @Nullable DhisToFhirTransformOutcome transform( @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, @Nonnull R input, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerServiceImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerServiceImpl.java index 53683e35..45da1791 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerServiceImpl.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerServiceImpl.java @@ -94,6 +94,8 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.UUID; import java.util.function.BiFunction; import java.util.function.Function; @@ -130,7 +132,7 @@ public class DhisToFhirTransformerServiceImpl implements DhisToFhirTransformerSe private final Map>> dataProviders = new HashMap<>(); - private final Map, DhisToFhirTransformer> transformers = new HashMap<>(); + private final Map, SortedSet>> transformers = new HashMap<>(); private final Map> transformerUtils = new HashMap<>(); @@ -159,8 +161,8 @@ public DhisToFhirTransformerServiceImpl( @Nonnull LockManager lockManager, this.scriptExecutor = scriptExecutor; this.scriptExecutionContext = scriptExecutionContext; - requestResolvers.ifAvailable( resolvers -> - resolvers.forEach( r -> this.requestResolvers.put( r.getDhisResourceType(), r ) ) ); + requestResolvers.ifAvailable( resolvers -> resolvers.forEach( r -> this.requestResolvers.put( r.getDhisResourceType(), r ) ) ); + dataProviders.ifAvailable( providers -> { for ( final DhisToFhirDataProvider dataProvider : providers ) @@ -171,16 +173,20 @@ public DhisToFhirTransformerServiceImpl( @Nonnull LockManager lockManager, } } } ); + transformersProvider.ifAvailable( transformers -> { for ( final DhisToFhirTransformer transformer : transformers ) { for ( final FhirVersion fhirVersion : transformer.getFhirVersions() ) { - this.transformers.put( new FhirVersionedValue<>( fhirVersion, transformer.getDhisResourceType() ), transformer ); + final FhirVersionedValue fhirVersionedValue = new FhirVersionedValue<>( fhirVersion, transformer.getDhisResourceType() ); + this.transformers.computeIfAbsent( new FhirVersionedValue<>( fhirVersion, transformer.getDhisResourceType() ), + fvv -> new TreeSet<>( Collections.reverseOrder() ) ).add( transformer ); } } } ); + transformUtilsProvider.ifAvailable( dhisToFhirTransformerUtils -> { for ( final DhisToFhirTransformerUtils tu : dhisToFhirTransformerUtils ) @@ -370,7 +376,7 @@ public DhisToFhirTransformerRequest createTransformerRequest( @Nonnull FhirClien final List> ruleInfos = requestResolver.resolveRules( scriptedDhisResource ); final RuleInfo matchingRuleInfo = ruleInfos.stream().filter( ri -> ri.getRule().getId().equals( ruleId ) ).findFirst().orElse( null ); - if ( (matchingRuleInfo == null) || !fhirResourceType.equals( matchingRuleInfo.getRule().getFhirResourceType() ) ) + if ( matchingRuleInfo == null || !fhirResourceType.equals( matchingRuleInfo.getRule().getFhirResourceType() ) ) { logger.info( "Could not find any matching rule to process DHIS resource." ); @@ -495,13 +501,13 @@ public DhisToFhirTransformOutcome transform( @Nonnull D } } - final DhisToFhirTransformer transformer = this.transformers.get( + final SortedSet> transformers = this.transformers.get( new FhirVersionedValue<>( transformerRequestImpl.getContext().getVersion(), ruleInfo.getRule().getDhisResourceType() ) ); - if ( transformer == null ) + + if ( transformers == null ) { throw new TransformerMappingException( "No transformer can be found for FHIR version " + - transformerRequestImpl.getContext().getVersion() + - " mapping of DHIS resource type " + ruleInfo.getRule().getDhisResourceType() ); + transformerRequestImpl.getContext().getVersion() + " mapping of DHIS resource type " + ruleInfo.getRule().getDhisResourceType() ); } final Map scriptVariables = new HashMap<>( transformerRequestImpl.getTransformerUtils() ); @@ -511,27 +517,35 @@ public DhisToFhirTransformOutcome transform( @Nonnull D scriptVariables.put( ScriptVariable.ORGANIZATION_UNIT.getVariableName(), getScriptedOrganizationUnit( transformerRequestImpl.getInput() ) ); if ( isApplicable( transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ) ) { - final DhisToFhirTransformOutcome outcome = transformer.transformCasted( transformerRequest.getFhirClient(), - transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ); - if ( outcome != null ) + for ( final DhisToFhirTransformer transformer : transformers ) { - logger.debug( "Rule {} used successfully for transformation of {} (stop={}).", - ruleInfo, transformerRequestImpl.getInput().getResourceId(), ruleInfo.getRule().isStop() ); - if ( (transformerRequestKey != null) && !outcome.isDelete() ) + final DhisToFhirTransformOutcome outcome = transformer.transformCasted( transformerRequest.getFhirClient(), + transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ); + + if ( outcome != null ) { - transformerRequestCache.put( transformerRequestKey, outcome.getResource() ); + logger.debug( "Rule {} used successfully for transformation of {} (stop={}).", + ruleInfo, transformerRequestImpl.getInput().getResourceId(), ruleInfo.getRule().isStop() ); + + if ( ( transformerRequestKey != null ) && !outcome.isDelete() ) + { + transformerRequestCache.put( transformerRequestKey, outcome.getResource() ); + } + + return new DhisToFhirTransformOutcome<>( outcome, transformerRequestImpl.isLastRule() ? null : transformerRequestImpl ); } - return new DhisToFhirTransformOutcome<>( outcome, transformerRequestImpl.isLastRule() ? null : transformerRequestImpl ); + // if the previous transformation caused a lock of any resource this must be released since the transformation has been rolled back + lockManager.getCurrentLockContext().ifPresent( LockContext::unlockAll ); } - // if the previous transformation caused a lock of any resource this must be released since the transformation has been rolled back - lockManager.getCurrentLockContext().ifPresent( LockContext::unlockAll ); } } + if ( firstRule ) { logger.debug( "No matching rule for {}.", transformerRequestImpl.getInput().getResourceId() ); } + return null; } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/orgunit/OrganizationUnitToFhirTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/orgunit/OrganizationUnitToFhirTransformer.java index 9fccb590..ead3aa22 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/orgunit/OrganizationUnitToFhirTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/metadata/orgunit/OrganizationUnitToFhirTransformer.java @@ -74,6 +74,7 @@ public OrganizationUnitToFhirTransformer( @Nonnull ScriptExecutor scriptExecutor @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull OrganizationUnitService organizationUnitService, @Nonnull ScriptExecutionContext scriptExecutionContext ) { super( scriptExecutor, lockManager, systemRepository, fhirResourceRepository, fhirDhisAssignmentRepository ); + this.organizationUnitService = organizationUnitService; this.scriptExecutionContext = scriptExecutionContext; } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/AbstractFhirToDhisTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/AbstractFhirToDhisTransformer.java index 8b93e04a..05813faf 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/AbstractFhirToDhisTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/AbstractFhirToDhisTransformer.java @@ -82,7 +82,7 @@ import java.util.Optional; /** - * Abstract base class for all transformers from FHIR to DHIS2 resources. + * Abstract base class for all transformers from FHIR to DHIS2 resources. The default priority of the transformer is 0. * * @param the concrete type of the FHIR resource. * @param the concrete type of transformation rule that this transformer processes. @@ -119,6 +119,25 @@ public AbstractFhirToDhisTransformer( @Nonnull ScriptExecutor scriptExecutor, @N this.valueConverter = valueConverter; } + @Override + public int getPriority() + { + return 0; + } + + @Override + public int compareTo( @Nonnull FhirToDhisTransformer o ) + { + final int value = getPriority() - o.getPriority(); + + if ( value != 0 ) + { + return value; + } + + return getClass().getSimpleName().compareTo( o.getClass().getSimpleName() ); + } + @Nullable @Override public FhirToDhisTransformOutcome transformCasted( @Nonnull FhirClientResource fhirClientResource, @Nonnull FhirToDhisTransformerContext context, @Nonnull IBaseResource input, diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformer.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformer.java index 7175fc96..a8a5e47f 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformer.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformer.java @@ -52,7 +52,7 @@ * @param the concrete type of the transformer rule that is processed by this transformer. * @author volsch */ -public interface FhirToDhisTransformer extends FhirVersionRestricted +public interface FhirToDhisTransformer extends FhirVersionRestricted, Comparable> { @Nonnull DhisResourceType getDhisResourceType(); @@ -63,6 +63,11 @@ public interface FhirToDhisTransformer getRuleClass(); + /** + * @return the priority of this transformer (matching transformers with a higher priority are used first). + */ + int getPriority(); + @Nullable FhirToDhisTransformOutcome transform( @Nonnull FhirClientResource fhirClientResource, @Nonnull FhirToDhisTransformerContext context, @Nonnull IBaseResource input, @Nonnull RuleInfo ruleInfo, @Nonnull Map scriptVariables ) throws TransformerException; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerServiceImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerServiceImpl.java index 6cff6c1b..effb503e 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerServiceImpl.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerServiceImpl.java @@ -71,6 +71,8 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; /** @@ -89,7 +91,7 @@ public class FhirToDhisTransformerServiceImpl implements FhirToDhisTransformerSe private final RuleRepository ruleRepository; - private final Map, FhirToDhisTransformer> transformers = new HashMap<>(); + private final Map, SortedSet>> transformers = new HashMap<>(); private final Map> transformerUtils = new HashMap<>(); @@ -112,10 +114,12 @@ public FhirToDhisTransformerServiceImpl( @Nonnull LockManager lockManager, { for ( final FhirVersion fhirVersion : transformer.getFhirVersions() ) { - this.transformers.put( new FhirVersionedValue<>( fhirVersion, transformer.getDhisResourceType() ), transformer ); + this.transformers.computeIfAbsent( new FhirVersionedValue<>( fhirVersion, transformer.getDhisResourceType() ), + fvv -> new TreeSet<>( Collections.reverseOrder() ) ).add( transformer ); } } } ); + transformUtilsProvider.ifAvailable( fhirToDhisTransformerUtils -> { for ( final FhirToDhisTransformerUtils tu : fhirToDhisTransformerUtils ) @@ -174,17 +178,27 @@ public FhirToDhisDeleteTransformOutcome delete( @Nonnull return null; } - final FhirToDhisTransformer transformer = this.transformers.get( + final SortedSet> transformers = this.transformers.get( new FhirVersionedValue<>( fhirClientResource.getFhirClient().getFhirVersion(), ruleInfo.getRule().getDhisResourceType() ) ); - if ( transformer == null ) + if ( transformers == null ) { throw new TransformerMappingException( "No transformer can be found for FHIR version " + - fhirClientResource.getFhirClient().getFhirVersion() + - " mapping of DHIS resource type " + ruleInfo.getRule().getDhisResourceType() ); + fhirClientResource.getFhirClient().getFhirVersion() + " mapping of DHIS resource type " + ruleInfo.getRule().getDhisResourceType() ); + } + + for ( final FhirToDhisTransformer transformer : transformers ) + { + final FhirToDhisDeleteTransformOutcome outcome = + transformer.transformDeletionCasted( fhirClientResource, ruleInfo, dhisFhirResourceId ); + + if ( outcome != null ) + { + return outcome; + } } - return transformer.transformDeletionCasted( fhirClientResource, ruleInfo, dhisFhirResourceId ); + return null; } @Nullable @@ -224,13 +238,13 @@ public FhirToDhisTransformOutcome transform( @Nonnull Fh RuleInfo ruleInfo; while ( (ruleInfo = transformerRequestImpl.nextRule()) != null ) { - final FhirToDhisTransformer transformer = this.transformers.get( + final SortedSet> transformers = this.transformers.get( new FhirVersionedValue<>( transformerRequestImpl.getContext().getFhirRequest().getVersion(), ruleInfo.getRule().getDhisResourceType() ) ); - if ( transformer == null ) + + if ( transformers == null ) { throw new TransformerMappingException( "No transformer can be found for FHIR version " + - transformerRequestImpl.getContext().getFhirRequest().getVersion() + - " mapping of DHIS resource type " + ruleInfo.getRule().getDhisResourceType() ); + transformerRequestImpl.getContext().getFhirRequest().getVersion() + " mapping of DHIS resource type " + ruleInfo.getRule().getDhisResourceType() ); } final Map scriptVariables = new HashMap<>( transformerUtils ); @@ -238,18 +252,23 @@ public FhirToDhisTransformOutcome transform( @Nonnull Fh scriptVariables.put( ScriptVariable.INPUT.getVariableName(), transformerRequestImpl.getInput() ); if ( isApplicable( transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ) ) { - final FhirToDhisTransformOutcome outcome = transformer.transformCasted( transformerRequest.getFhirClientResource(), - transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ); - if ( outcome != null ) + for ( final FhirToDhisTransformer transformer : transformers ) { - logger.info( "Rule {} used successfully for transformation of {} (stop={}).", - ruleInfo, transformerRequestImpl.getInput().getIdElement(), ruleInfo.getRule().isStop() ); - transformerRequestImpl.executed( ruleInfo ); - return new FhirToDhisTransformOutcome<>( outcome, (ruleInfo.getRule().isStop() || transformerRequestImpl.isLastRule()) ? null : transformerRequestImpl ); - } + final FhirToDhisTransformOutcome outcome = transformer.transformCasted( transformerRequest.getFhirClientResource(), + transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ); - // if the previous transformation caused a lock of any resource this must be released since the transformation has been rolled back - lockManager.getCurrentLockContext().ifPresent( LockContext::unlockAll ); + if ( outcome != null ) + { + logger.info( "Rule {} used successfully for transformation of {} (stop={}).", + ruleInfo, transformerRequestImpl.getInput().getIdElement(), ruleInfo.getRule().isStop() ); + transformerRequestImpl.executed( ruleInfo ); + + return new FhirToDhisTransformOutcome<>( outcome, ( ruleInfo.getRule().isStop() || transformerRequestImpl.isLastRule() ) ? null : transformerRequestImpl ); + } + + // if the previous transformation caused a lock of any resource this must be released since the transformation has been rolled back + lockManager.getCurrentLockContext().ifPresent( LockContext::unlockAll ); + } } }