Skip to content

Commit

Permalink
Added support for multiple transformers for one resource type.
Browse files Browse the repository at this point in the history
Tests are still missing.
  • Loading branch information
volsch committed Aug 18, 2019
1 parent b05c0eb commit faeab2c
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>0</code>.
*
* @param <R> the concrete type of the DHIS2 resource that is processed by this transformer.
* @param <U> the concrete type of the transformer rule that is processed by this transformer.
Expand Down Expand Up @@ -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()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
* @param <U> the concrete type of the transformer rule that is processed by this transformer.
* @author volsch
*/
public interface DhisToFhirTransformer<R extends ScriptedDhisResource, U extends AbstractRule> extends FhirVersionRestricted
public interface DhisToFhirTransformer<R extends ScriptedDhisResource, U extends AbstractRule> extends FhirVersionRestricted, Comparable<DhisToFhirTransformer<?, ?>>
{
@Nonnull
DhisResourceType getDhisResourceType();
Expand All @@ -61,6 +61,11 @@ public interface DhisToFhirTransformer<R extends ScriptedDhisResource, U extends
@Nonnull
Class<U> getRuleClass();

/**
* @return the priority of this transformer (matching transformers with a higher priority are used first).
*/
int getPriority();

@Nullable
DhisToFhirTransformOutcome<? extends IBaseResource> transform( @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, @Nonnull R input, @Nonnull RuleInfo<U> ruleInfo,
@Nonnull Map<String, Object> scriptVariables ) throws TransformerException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -130,7 +132,7 @@ public class DhisToFhirTransformerServiceImpl implements DhisToFhirTransformerSe

private final Map<FhirVersion, Map<DhisResourceType, DhisToFhirDataProvider<? extends AbstractRule>>> dataProviders = new HashMap<>();

private final Map<FhirVersionedValue<DhisResourceType>, DhisToFhirTransformer<?, ?>> transformers = new HashMap<>();
private final Map<FhirVersionedValue<DhisResourceType>, SortedSet<DhisToFhirTransformer<?, ?>>> transformers = new HashMap<>();

private final Map<FhirVersion, Map<String, DhisToFhirTransformerUtils>> transformerUtils = new HashMap<>();

Expand Down Expand Up @@ -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 )
Expand All @@ -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<DhisResourceType> 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 )
Expand Down Expand Up @@ -370,7 +376,7 @@ public DhisToFhirTransformerRequest createTransformerRequest( @Nonnull FhirClien
final List<RuleInfo<? extends AbstractRule>> ruleInfos = requestResolver.resolveRules( scriptedDhisResource );
final RuleInfo<? extends AbstractRule> 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." );

Expand Down Expand Up @@ -495,13 +501,13 @@ public DhisToFhirTransformOutcome<? extends IBaseResource> transform( @Nonnull D
}
}

final DhisToFhirTransformer<?, ?> transformer = this.transformers.get(
final SortedSet<DhisToFhirTransformer<?, ?>> 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<String, Object> scriptVariables = new HashMap<>( transformerRequestImpl.getTransformerUtils() );
Expand All @@ -511,27 +517,35 @@ public DhisToFhirTransformOutcome<? extends IBaseResource> transform( @Nonnull D
scriptVariables.put( ScriptVariable.ORGANIZATION_UNIT.getVariableName(), getScriptedOrganizationUnit( transformerRequestImpl.getInput() ) );
if ( isApplicable( transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ) )
{
final DhisToFhirTransformOutcome<? extends IBaseResource> 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<? extends IBaseResource> 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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>0</code>.
*
* @param <R> the concrete type of the FHIR resource.
* @param <U> the concrete type of transformation rule that this transformer processes.
Expand Down Expand Up @@ -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<R> transformCasted( @Nonnull FhirClientResource fhirClientResource, @Nonnull FhirToDhisTransformerContext context, @Nonnull IBaseResource input,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
* @param <U> the concrete type of the transformer rule that is processed by this transformer.
* @author volsch
*/
public interface FhirToDhisTransformer<R extends DhisResource, U extends AbstractRule> extends FhirVersionRestricted
public interface FhirToDhisTransformer<R extends DhisResource, U extends AbstractRule> extends FhirVersionRestricted, Comparable<FhirToDhisTransformer<?, ?>>
{
@Nonnull
DhisResourceType getDhisResourceType();
Expand All @@ -63,6 +63,11 @@ public interface FhirToDhisTransformer<R extends DhisResource, U extends Abstrac
@Nonnull
Class<U> getRuleClass();

/**
* @return the priority of this transformer (matching transformers with a higher priority are used first).
*/
int getPriority();

@Nullable
FhirToDhisTransformOutcome<R> transform( @Nonnull FhirClientResource fhirClientResource, @Nonnull FhirToDhisTransformerContext context, @Nonnull IBaseResource input,
@Nonnull RuleInfo<U> ruleInfo, @Nonnull Map<String, Object> scriptVariables ) throws TransformerException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -89,7 +91,7 @@ public class FhirToDhisTransformerServiceImpl implements FhirToDhisTransformerSe

private final RuleRepository ruleRepository;

private final Map<FhirVersionedValue<DhisResourceType>, FhirToDhisTransformer<?, ?>> transformers = new HashMap<>();
private final Map<FhirVersionedValue<DhisResourceType>, SortedSet<FhirToDhisTransformer<?, ?>>> transformers = new HashMap<>();

private final Map<FhirVersion, Map<String, FhirToDhisTransformerUtils>> transformerUtils = new HashMap<>();

Expand All @@ -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 )
Expand Down Expand Up @@ -174,17 +178,27 @@ public FhirToDhisDeleteTransformOutcome<? extends DhisResource> delete( @Nonnull
return null;
}

final FhirToDhisTransformer<?, ?> transformer = this.transformers.get(
final SortedSet<FhirToDhisTransformer<?, ?>> 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<? extends DhisResource> outcome =
transformer.transformDeletionCasted( fhirClientResource, ruleInfo, dhisFhirResourceId );

if ( outcome != null )
{
return outcome;
}
}

return transformer.transformDeletionCasted( fhirClientResource, ruleInfo, dhisFhirResourceId );
return null;
}

@Nullable
Expand Down Expand Up @@ -224,32 +238,37 @@ public FhirToDhisTransformOutcome<? extends DhisResource> transform( @Nonnull Fh
RuleInfo<? extends AbstractRule> ruleInfo;
while ( (ruleInfo = transformerRequestImpl.nextRule()) != null )
{
final FhirToDhisTransformer<?, ?> transformer = this.transformers.get(
final SortedSet<FhirToDhisTransformer<?, ?>> 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<String, Object> scriptVariables = new HashMap<>( transformerUtils );
scriptVariables.put( ScriptVariable.CONTEXT.getVariableName(), transformerRequestImpl.getContext() );
scriptVariables.put( ScriptVariable.INPUT.getVariableName(), transformerRequestImpl.getInput() );
if ( isApplicable( transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), ruleInfo, scriptVariables ) )
{
final FhirToDhisTransformOutcome<? extends DhisResource> 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<? extends DhisResource> 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 );
}
}
}

Expand Down

0 comments on commit faeab2c

Please sign in to comment.