Skip to content

Commit

Permalink
Special handling for created and updated resources for REST interfaces.
Browse files Browse the repository at this point in the history
  • Loading branch information
volsch committed Mar 16, 2019
1 parent 4936d13 commit 66fbea5
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.dhis2.fhir.adapter.fhir.repository.FhirRepositoryOperation;
import org.dhis2.fhir.adapter.fhir.repository.FhirRepositoryOperationOutcome;
import org.dhis2.fhir.adapter.fhir.repository.FhirResourceRepository;
import org.dhis2.fhir.adapter.fhir.transform.DhisDataExistsException;
import org.dhis2.fhir.adapter.fhir.transform.FatalTransformerException;
import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException;
import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException;
Expand Down Expand Up @@ -147,7 +148,7 @@ public FhirRepositoryImpl( @Nonnull AuthorizationContext authorizationContext,

@Override
@Nullable
@HystrixCommand( ignoreExceptions = { DhisConflictException.class, TransformerDataException.class, TransformerMappingException.class, TrackedEntityInstanceNotFoundException.class } )
@HystrixCommand( ignoreExceptions = { DhisConflictException.class, TransformerDataException.class, TransformerMappingException.class, TrackedEntityInstanceNotFoundException.class, DhisDataExistsException.class } )
@Transactional( propagation = Propagation.NOT_SUPPORTED )
public FhirRepositoryOperationOutcome save( @Nonnull FhirClientResource fhirClientResource, @Nonnull IBaseResource resource, @Nullable FhirRepositoryOperation fhirRepositoryOperation )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter;
import org.dhis2.fhir.adapter.dhis.DhisConflictException;
import org.dhis2.fhir.adapter.fhir.transform.DhisDataExistsException;
import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException;
import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirDataProviderException;
import org.dhis2.fhir.adapter.fhir.transform.fhir.TrackedEntityInstanceNotFoundException;
Expand Down Expand Up @@ -62,7 +63,7 @@ public BaseServerResponseException preProcessOutgoingException( RequestDetails t
{
final BaseServerResponseException result;
final Throwable unprocessableEntityException = ExceptionUtils.findCause( theException, DhisConflictException.class,
TransformerDataException.class, TrackedEntityInstanceNotFoundException.class, DhisToFhirDataProviderException.class );
TransformerDataException.class, TrackedEntityInstanceNotFoundException.class, DhisToFhirDataProviderException.class, DhisDataExistsException.class );
if ( unprocessableEntityException != null )
{
log.info( "Request could not be processed because of an error: {}", unprocessableEntityException.getMessage() );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.dhis2.fhir.adapter.fhir.transform;

/*
* 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 data to be transformed exists already and cannot be created again.
*
* @author volsch
*/
public class DhisDataExistsException extends RuntimeException
{
private static final long serialVersionUID = 507760404334717694L;

public DhisDataExistsException( String message )
{
super( message );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,30 +136,34 @@ public Set<FhirVersion> getFhirVersions()
protected Optional<R> getResource( @Nonnull FhirClientResource fhirClientResource, @Nonnull FhirToDhisTransformerContext context,
@Nonnull RuleInfo<U> ruleInfo, @Nonnull Map<String, Object> scriptVariables ) throws TransformerException
{
if ( context.getFhirRequest().getRequestMethod() != FhirRequestMethod.CREATE )
boolean activeResource = true;
if ( context.getFhirRequest().isDhisFhirId() )
{
if ( context.getFhirRequest().isDhisFhirId() )
final String id = getDhisId( context, ruleInfo );
if ( id != null )
{
final String id = getDhisId( context, ruleInfo );
R resource = getResourceById( id ).orElse( null );
if ( resource != null )
{
return Optional.of( resource );
}
activeResource = false;
}
else
}
else
{
final R resource = getResourceByAssignment( fhirClientResource, context, ruleInfo, scriptVariables ).orElse( null );
if ( resource != null )
{
R resource = getResourceByAssignment( fhirClientResource, context, ruleInfo, scriptVariables ).orElse( null );
if ( resource != null )
{
return Optional.of( resource );
}

resource = getActiveResource( context, ruleInfo, scriptVariables, false ).orElse( null );
if ( resource != null )
{
return Optional.of( resource );
}
return Optional.of( resource );
}
}
if ( activeResource )
{
final R resource = getActiveResource( context, ruleInfo, scriptVariables, false ).orElse( null );
if ( resource != null )
{
return Optional.of( resource );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import org.apache.commons.lang3.StringUtils;
import org.dhis2.fhir.adapter.dhis.converter.ValueConverter;
import org.dhis2.fhir.adapter.dhis.model.DhisResourceType;
import org.dhis2.fhir.adapter.dhis.model.Reference;
Expand All @@ -43,6 +44,7 @@
import org.dhis2.fhir.adapter.dhis.tracker.program.Program;
import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService;
import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramStage;
import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramStageDataElement;
import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramTrackedEntityAttribute;
import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityAttributes;
import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityInstance;
Expand All @@ -54,17 +56,20 @@
import org.dhis2.fhir.adapter.fhir.metadata.model.FhirResourceMapping;
import org.dhis2.fhir.adapter.fhir.metadata.model.MappedTrackerProgram;
import org.dhis2.fhir.adapter.fhir.metadata.model.ProgramStageRule;
import org.dhis2.fhir.adapter.fhir.metadata.model.RuleDhisDataReference;
import org.dhis2.fhir.adapter.fhir.metadata.model.RuleInfo;
import org.dhis2.fhir.adapter.fhir.metadata.model.ScriptVariable;
import org.dhis2.fhir.adapter.fhir.metadata.repository.FhirResourceMappingRepository;
import org.dhis2.fhir.adapter.fhir.model.EventDecisionType;
import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor;
import org.dhis2.fhir.adapter.fhir.transform.DhisDataExistsException;
import org.dhis2.fhir.adapter.fhir.transform.FatalTransformerException;
import org.dhis2.fhir.adapter.fhir.transform.TransformerException;
import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException;
import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformOutcome;
import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext;
import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.AbstractFhirToDhisTransformer;
import org.dhis2.fhir.adapter.fhir.transform.fhir.model.FhirRequestMethod;
import org.dhis2.fhir.adapter.fhir.transform.scripted.ImmutableScriptedEnrollment;
import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedEnrollment;
import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedTrackedEntityInstance;
Expand Down Expand Up @@ -200,6 +205,12 @@ public FhirToDhisTransformOutcome<Event> transform( @Nonnull FhirClientResource
return null;
}

boolean oldEmpty = true;
if ( !event.isNewResource() )
{
oldEmpty = !hasRequiredDataElements( context, ruleInfo, programStage, event );
}

if ( !isStatusApplicable( ruleInfo, event ) )
{
return null;
Expand All @@ -218,6 +229,10 @@ public FhirToDhisTransformOutcome<Event> transform( @Nonnull FhirClientResource
{
return null;
}
if ( !oldEmpty && ( context.getFhirRequest().getRequestMethod() == FhirRequestMethod.CREATE ) )
{
throw new DhisDataExistsException( "Required data elements contain data already." );
}
updateCoordinates( context, ruleInfo, resourceMapping, program, scriptedEnrollment, programStage, scriptedEvent, variables );

if ( !afterEvent( context, ruleInfo, programStage, scriptVariables ) ||
Expand Down Expand Up @@ -290,6 +305,35 @@ protected void updateCoordinates( @Nonnull FhirToDhisTransformerContext context,
}
}

protected boolean hasRequiredDataElements( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo<ProgramStageRule> ruleInfo, @Nonnull ProgramStage programStage, @Nonnull Event event )
{
if ( event.isNewResource() )
{
return false;
}
boolean anyRequired = false;
for ( RuleDhisDataReference r : ruleInfo.getDhisDataReferences() )
{
if ( r.isRequired() )
{
if ( !hasDataElementValue( context, ruleInfo, programStage, event, r.getDataReference() ) )
{
return false;
}
anyRequired = true;
}
}
return anyRequired;
}

protected boolean hasDataElementValue( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo<ProgramStageRule> ruleInfo, @Nonnull ProgramStage programStage, @Nonnull Event event, @Nonnull Reference dataElementRef )
{
final ProgramStageDataElement dataElement = programStage.getOptionalDataElement( dataElementRef )
.orElseThrow( () -> new TransformerMappingException( "Rule " + ruleInfo + " contains data element reference " + dataElementRef + " that is not defined by program stage \"" + programStage.getName() + "\"." ) );
final Object value = event.getDataValue( dataElement.getElementId() ).getValue();
return ( value != null ) && ( !( value instanceof String ) || StringUtils.isNotBlank( (String) value ) );
}

@Override
protected boolean isSyncRequired( @Nonnull FhirToDhisTransformerContext context, @Nonnull RuleInfo<ProgramStageRule> ruleInfo, @Nonnull Map<String, Object> scriptVariables ) throws TransformerException
{
Expand Down

0 comments on commit 66fbea5

Please sign in to comment.