diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/AbstractDhisType.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/AbstractDhisType.java new file mode 100644 index 00000000..1950bcb1 --- /dev/null +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/AbstractDhisType.java @@ -0,0 +1,67 @@ +package org.dhis2.fhir.adapter.dhis.model; + +/* + * Copyright (c) 2004-2018, 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 com.fasterxml.jackson.annotation.JsonIgnore; + +import javax.annotation.Nonnull; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +/** + * Abstract implementation of {@link DhisType}. + * + * @author volsch + */ +public abstract class AbstractDhisType implements DhisType, Serializable +{ + private static final long serialVersionUID = 7960220674294587120L; + + @JsonIgnore + @Nonnull + @Override + public Set getAllReferences() + { + final Set references = new HashSet<>(); + if ( getId() != null ) + { + references.add( new Reference( getId(), ReferenceType.ID ) ); + } + if ( getCode() != null ) + { + references.add( new Reference( getCode(), ReferenceType.CODE ) ); + } + if ( getName() != null ) + { + references.add( new Reference( getName(), ReferenceType.NAME ) ); + } + return references; + } +} diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/DhisType.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/DhisType.java new file mode 100644 index 00000000..a20adb38 --- /dev/null +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/model/DhisType.java @@ -0,0 +1,58 @@ +package org.dhis2.fhir.adapter.dhis.model; + +/* + * Copyright (c) 2004-2018, 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.dhis2.fhir.adapter.model.Identifiable; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * Implemented by DHIS 2 types. + * + * @author volsch + */ +public interface DhisType extends Identifiable +{ + /** + * @return the unique code of the type or null if the type has no code. + */ + String getCode(); + + /** + * @return the unique name of the type. + */ + String getName(); + + /** + * @return all references that can be used to reference this type. + */ + @Nonnull + Set getAllReferences(); +} diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/sync/impl/DhisResourceRepositoryImpl.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/sync/impl/DhisResourceRepositoryImpl.java index 18389970..5df3b44c 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/sync/impl/DhisResourceRepositoryImpl.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/sync/impl/DhisResourceRepositoryImpl.java @@ -34,7 +34,9 @@ import org.dhis2.fhir.adapter.dhis.tracker.program.EnrollmentService; import org.dhis2.fhir.adapter.dhis.tracker.program.Event; import org.dhis2.fhir.adapter.dhis.tracker.program.EventService; +import org.dhis2.fhir.adapter.dhis.tracker.program.ProgramMetadataService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityInstance; +import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityMetadataService; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,18 +59,22 @@ public class DhisResourceRepositoryImpl implements DhisResourceRepository private final TrackedEntityService trackedEntityService; + private final TrackedEntityMetadataService trackedEntityMetadataService; + private final EnrollmentService enrollmentService; private final EventService eventService; - public DhisResourceRepositoryImpl( - @Nonnull TrackedEntityService trackedEntityService, - @Nonnull EnrollmentService enrollmentService, - @Nonnull EventService eventService ) + private final ProgramMetadataService programMetadataService; + + public DhisResourceRepositoryImpl( @Nonnull TrackedEntityService trackedEntityService, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService, + @Nonnull EnrollmentService enrollmentService, @Nonnull EventService eventService, @Nonnull ProgramMetadataService programMetadataService ) { this.trackedEntityService = trackedEntityService; + this.trackedEntityMetadataService = trackedEntityMetadataService; this.enrollmentService = enrollmentService; this.eventService = eventService; + this.programMetadataService = programMetadataService; } @Nonnull @@ -174,5 +180,4 @@ private boolean saveEvent( @Nonnull Event event ) return updated; } - } diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgram.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgram.java index 18ee9a67..7de50df5 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgram.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgram.java @@ -38,6 +38,7 @@ import java.io.Serializable; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; public class ImmutableProgram implements Program, Serializable @@ -53,6 +54,14 @@ public ImmutableProgram( @Nonnull @JsonProperty( "delegate" ) WritableProgram de this.delegate = delegate; } + @JsonIgnore + @Override + @Nonnull + public Set getAllReferences() + { + return delegate.getAllReferences(); + } + @JsonIgnore @Override public String getId() diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgramStage.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgramStage.java index d25515b9..ad66c908 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgramStage.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ImmutableProgramStage.java @@ -38,6 +38,7 @@ import java.io.Serializable; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; public class ImmutableProgramStage implements ProgramStage, Serializable @@ -53,6 +54,14 @@ public ImmutableProgramStage( @Nonnull @JsonProperty( "delegate" ) WritableProgr this.delegate = delegate; } + @JsonIgnore + @Override + @Nonnull + public Set getAllReferences() + { + return delegate.getAllReferences(); + } + @JsonIgnore @Override public String getId() @@ -60,6 +69,13 @@ public String getId() return delegate.getId(); } + @JsonIgnore + @Override + public String getCode() + { + return delegate.getCode(); + } + @JsonIgnore @Override public String getName() diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/Program.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/Program.java index 829e5f8d..38a229b0 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/Program.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/Program.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.scriptable.Scriptable; @@ -44,14 +45,8 @@ * @author volsch */ @Scriptable -public interface Program +public interface Program extends DhisType { - String getId(); - - String getName(); - - String getCode(); - String getTrackedEntityTypeId(); boolean isSelectIncidentDatesInFuture(); diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ProgramStage.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ProgramStage.java index 6f63478d..92920761 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ProgramStage.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/ProgramStage.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.scriptable.Scriptable; @@ -44,12 +45,8 @@ * @author volsch */ @Scriptable -public interface ProgramStage +public interface ProgramStage extends DhisType { - String getId(); - - String getName(); - boolean isRepeatable(); boolean isCaptureCoordinates(); diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgram.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgram.java index 0d996865..af908e0c 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgram.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgram.java @@ -31,6 +31,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import org.dhis2.fhir.adapter.dhis.model.AbstractDhisType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.model.Id; @@ -42,7 +43,7 @@ import java.util.Optional; import java.util.stream.Collectors; -public class WritableProgram implements Program, Serializable +public class WritableProgram extends AbstractDhisType implements Program, Serializable { private static final long serialVersionUID = -4906529875383953995L; diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgramStage.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgramStage.java index 20f7730e..70f81948 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgramStage.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/program/WritableProgramStage.java @@ -30,6 +30,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import org.dhis2.fhir.adapter.dhis.model.AbstractDhisType; import org.dhis2.fhir.adapter.dhis.model.Reference; import javax.annotation.Nonnull; @@ -40,7 +41,7 @@ import java.util.Optional; import java.util.stream.Collectors; -public class WritableProgramStage implements ProgramStage, Serializable +public class WritableProgramStage extends AbstractDhisType implements ProgramStage, Serializable { private static final long serialVersionUID = -7544648580734783374L; @@ -90,6 +91,13 @@ public void setName( String name ) this.name = name; } + @Override + public String getCode() + { + // program stages do not have a code + return null; + } + @Override public boolean isRepeatable() { diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/ImmutableTrackedEntityType.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/ImmutableTrackedEntityType.java index 14cc2369..e0256641 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/ImmutableTrackedEntityType.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/ImmutableTrackedEntityType.java @@ -39,6 +39,7 @@ import java.io.Serializable; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; @Scriptable @@ -55,6 +56,14 @@ public ImmutableTrackedEntityType( @Nonnull @JsonProperty( "delegate" ) Writable this.delegate = delegate; } + @JsonIgnore + @Override + @Nonnull + public Set getAllReferences() + { + return delegate.getAllReferences(); + } + @JsonIgnore @Override public String getId() @@ -62,6 +71,13 @@ public String getId() return delegate.getId(); } + @JsonIgnore + @Override + public String getCode() + { + return delegate.getCode(); + } + @JsonIgnore @Override public String getName() diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityType.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityType.java index a948035d..23f32386 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityType.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/TrackedEntityType.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisType; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.scriptable.Scriptable; @@ -37,12 +38,8 @@ import java.util.Optional; @Scriptable -public interface TrackedEntityType +public interface TrackedEntityType extends DhisType { - String getId(); - - String getName(); - List getAttributes(); @Nonnull diff --git a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/WritableTrackedEntityType.java b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/WritableTrackedEntityType.java index 9a25869e..515a4829 100644 --- a/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/WritableTrackedEntityType.java +++ b/dhis/src/main/java/org/dhis2/fhir/adapter/dhis/tracker/trackedentity/WritableTrackedEntityType.java @@ -31,6 +31,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.lang3.StringUtils; +import org.dhis2.fhir.adapter.dhis.model.AbstractDhisType; import org.dhis2.fhir.adapter.dhis.model.Reference; import javax.annotation.Nonnull; @@ -41,7 +42,7 @@ import java.util.Optional; import java.util.stream.Collectors; -public class WritableTrackedEntityType implements TrackedEntityType, Serializable +public class WritableTrackedEntityType extends AbstractDhisType implements TrackedEntityType, Serializable { private static final long serialVersionUID = 797154293863611491L; @@ -95,6 +96,13 @@ public void setName( String name ) this.name = name; } + @Override + public String getCode() + { + // tracked entity types do no have a code + return null; + } + @Override public List getAttributes() { 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 86043c9f..6b9b42b4 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 @@ -67,10 +67,10 @@ @DiscriminatorColumn( name = "dhis_resource_type", discriminatorType = DiscriminatorType.STRING ) @NamedQueries( { @NamedQuery( name = AbstractRule.FIND_RULES_BY_TYPE_NAMED_QUERY, query = "SELECT r FROM AbstractRule r " + - "WHERE r.fhirResourceType=:fhirResourceType AND r.applicableCodeSet IS NULL AND r.enabled=true" ), + "WHERE r.fhirResourceType=:fhirResourceType AND r.applicableCodeSet IS NULL AND r.enabled=true AND r.inEnabled=true" ), @NamedQuery( name = AbstractRule.FIND_RULES_BY_TYPE_CODES_NAMED_QUERY, query = - "SELECT r FROM AbstractRule r WHERE r.fhirResourceType=:fhirResourceType AND r.enabled=true AND " + - "(r.applicableCodeSet IS NULL OR (r.applicableCodeSet IS NOT NULL AND EXISTS " + + "SELECT r FROM AbstractRule r WHERE r.fhirResourceType=:fhirResourceType AND r.enabled=true " + + "AND r.inEnabled=true AND (r.applicableCodeSet IS NULL OR (r.applicableCodeSet IS NOT NULL AND EXISTS " + "(SELECT 1 FROM CodeSetValue csv JOIN csv.code c JOIN c.systemCodes sc ON sc.systemCodeValue IN (:systemCodeValues) " + "JOIN sc.system s ON s.enabled=true WHERE csv.codeSet=r.applicableCodeSet AND csv.enabled=true)))" ) } ) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, property = "dhisResourceType", include = JsonTypeInfo.As.EXISTING_PROPERTY ) @@ -106,10 +106,16 @@ public abstract class AbstractRule extends VersionedBaseMetadata implements Seri @EnumValue( FhirResourceType.class ) private FhirResourceType fhirResourceType; + private boolean inEnabled; + + private boolean outEnabled; + private ExecutableScript applicableInScript; private CodeSet applicableCodeSet; + private ExecutableScript applicableOutScript; + @NotNull private ExecutableScript transformInScript; @@ -217,7 +223,43 @@ public void setApplicableCodeSet( CodeSet applicableCodeSet ) this.applicableCodeSet = applicableCodeSet; } - @ManyToOne( optional = false ) + @ManyToOne + @JoinColumn( name = "applicable_out_script_id", referencedColumnName = "id" ) + public ExecutableScript getApplicableOutScript() + { + return applicableOutScript; + } + + public void setApplicableOutScript( ExecutableScript applicableOutScript ) + { + this.applicableOutScript = applicableOutScript; + } + + @Basic + @Column( name = "in_enabled", nullable = false, columnDefinition = "BOOLEAN DEFAULT TRUE NOT NULL" ) + public boolean isInEnabled() + { + return inEnabled; + } + + public void setInEnabled( boolean inEnabled ) + { + this.inEnabled = inEnabled; + } + + @Basic + @Column( name = "out_enabled", nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE NOT NULL" ) + public boolean isOutEnabled() + { + return outEnabled; + } + + public void setOutEnabled( boolean outEnabled ) + { + this.outEnabled = outEnabled; + } + + @ManyToOne @JoinColumn( name = "transform_in_script_id", referencedColumnName = "id", nullable = false ) public ExecutableScript getTransformInScript() { 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 73e9839b..f8d81041 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 @@ -67,7 +67,6 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.time.Instant; import java.util.Objects; import java.util.Optional; @@ -111,8 +110,7 @@ public DhisRepositoryImpl( @Nonnull QueuedDhisResourceRepository queuedDhisResourceRepository, @Nonnull StoredDhisResourceService storedItemService, @Nonnull DhisResourceRepository dhisResourceRepository, - // TODO - @Nullable DhisToFhirTransformerService dhisToFhirTransformerService, + @Nonnull DhisToFhirTransformerService dhisToFhirTransformerService, @Nonnull RemoteFhirResourceRepository remoteFhirResourceRepository ) { this.authorizationContext = authorizationContext; @@ -227,8 +225,13 @@ protected boolean saveInternally( @Nonnull DhisSyncGroup subscriptionResource, @ dhisRequest.setResourceType( resource.getResourceType() ); dhisRequest.setLastUpdated( resource.getLastUpdated() ); - boolean saved = false; DhisToFhirTransformerRequest transformerRequest = dhisToFhirTransformerService.createTransformerRequest( dhisRequest, resource ); + if ( transformerRequest == null ) + { + return false; + } + + boolean saved = false; do { DhisToFhirTransformOutcome outcome; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/TransformationConfig.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/config/TransformationConfig.java similarity index 98% rename from fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/TransformationConfig.java rename to fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/config/TransformationConfig.java index 5133fd3c..9365f6ba 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/TransformationConfig.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/config/TransformationConfig.java @@ -1,4 +1,4 @@ -package org.dhis2.fhir.adapter.fhir.transform.fhir.impl; +package org.dhis2.fhir.adapter.fhir.transform.config; /* * Copyright (c) 2004-2018, University of Oslo diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerContext.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerContext.java index b679200a..cb3f1179 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerContext.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerContext.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; import org.dhis2.fhir.adapter.fhir.transform.dhis.model.DhisRequest; import org.dhis2.fhir.adapter.scriptable.ScriptMethod; @@ -51,6 +52,14 @@ public interface DhisToFhirTransformerContext @ScriptMethod( description = "Returns the DHIS request (type DhisRequest) that causes the current transformation execution." ) DhisRequest getDhisRequest(); + @Nonnull + @ScriptMethod( description = "Returns the FHIR version of the processed FHIR resource as Java enumeration (e.g. DSTU3 as enum constant)." ) + FhirVersion getVersion(); + + @Nonnull + @ScriptMethod( description = "Returns the code of the remote subscription that is associated with the execution of the current transformation." ) + String getRemoteSubscriptionCode(); + @Nonnull @ScriptMethod( description = "Returns the current timestamp as date/time.", returnDescription = "The current timestamp as date/time." ) ZonedDateTime now(); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerRequest.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerRequest.java index a6d19ad2..5213452d 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerRequest.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerRequest.java @@ -28,7 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import org.hl7.fhir.instance.model.api.IBaseResource; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedDhisResource; import javax.annotation.Nonnull; import java.io.Serializable; @@ -48,5 +48,5 @@ public interface DhisToFhirTransformerRequest extends Serializable DhisToFhirTransformerContext getContext(); @Nonnull - IBaseResource getInput(); + ScriptedDhisResource getInput(); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerService.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerService.java index c8c7c7ad..0ff86ecf 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerService.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/DhisToFhirTransformerService.java @@ -31,6 +31,7 @@ import org.dhis2.fhir.adapter.dhis.model.DhisResource; import org.dhis2.fhir.adapter.fhir.transform.TransformerException; import org.dhis2.fhir.adapter.fhir.transform.dhis.model.DhisRequest; +import org.hl7.fhir.instance.model.api.IBaseResource; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -42,9 +43,9 @@ */ public interface DhisToFhirTransformerService { - @Nonnull + @Nullable DhisToFhirTransformerRequest createTransformerRequest( @Nonnull DhisRequest dhisRequest, @Nonnull DhisResource resource ); @Nullable - DhisToFhirTransformOutcome transform( @Nonnull DhisToFhirTransformerRequest transformerRequest ) throws TransformerException; + DhisToFhirTransformOutcome transform( @Nonnull DhisToFhirTransformerRequest transformerRequest ) throws TransformerException; } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisBeanTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisBeanTransformerUtils.java new file mode 100644 index 00000000..c7e0e645 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisBeanTransformerUtils.java @@ -0,0 +1,68 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl; + +/* + * Copyright (c) 2004-2018, 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.beanutils.BeanUtils; +import org.dhis2.fhir.adapter.dhis.model.DhisResource; +import org.dhis2.fhir.adapter.fhir.transform.FatalTransformerException; + +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; + +/** + * Transformer utilities that clone a bean (cached instances must not be modified + * by several thread, e.g. DHIS 2 objects). + * + * @author volsch + */ +public abstract class DhisBeanTransformerUtils +{ + @Nullable + @SuppressWarnings( { "unchecked" } ) + public static T clone( @Nullable T object ) + { + if ( object == null ) + { + return null; + } + try + { + return (T) BeanUtils.cloneBean( object ); + } + catch ( IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e ) + { + throw new FatalTransformerException( "Could not clone DHIS resource.", e ); + } + } + + private DhisBeanTransformerUtils() + { + super(); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirRuleResolver.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirRuleResolver.java new file mode 100644 index 00000000..2368579f --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirRuleResolver.java @@ -0,0 +1,62 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl; + +/* + * Copyright (c) 2004-2018, 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.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.RemoteSubscription; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedDhisResource; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; + +/** + * Resolves the rules for transformations from DHIS 2 resources to FHIR resources + * depending on the DHIS 2 resource type. + * + * @author volsch + */ +public interface DhisToFhirRuleResolver +{ + @Nonnull + DhisResourceType getDhisResourceType(); + + @Nonnull + List resolveRule( @Nonnull DhisResource dhisResource ); + + @Nullable + RemoteSubscription resolveRemoteSubscription( @Nonnull DhisResource dhisResource, + Collection possibleRules ); + + @Nonnull + ScriptedDhisResource convert( @Nonnull DhisResource dhisResource ); +} 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 new file mode 100644 index 00000000..5dd0b02d --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformer.java @@ -0,0 +1,70 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl; + +/* + * Copyright (c) 2004-2018, 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.dhis2.fhir.adapter.dhis.model.DhisResourceType; +import org.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; +import org.dhis2.fhir.adapter.fhir.model.FhirVersionRestricted; +import org.dhis2.fhir.adapter.fhir.transform.TransformerException; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformOutcome; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedDhisResource; +import org.hl7.fhir.instance.model.api.IBaseResource; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Map; + +/** + * Transforms a DHIS 2 resource to a FHIR resource. + * + * @param the concrete type of the DHIS 2 resource that is processed by this transformer. + * @param the concrete type of the transformer rule that is processed by this transformer. + * @author volsch + */ +public interface DhisToFhirTransformer extends FhirVersionRestricted +{ + @Nonnull + DhisResourceType getDhisResourceType(); + + @Nonnull + Class getDhisResourceClass(); + + @Nonnull + Class getRuleClass(); + + @Nullable + DhisToFhirTransformOutcome transform( @Nonnull DhisToFhirTransformerContext context, @Nonnull R input, @Nonnull U rule, + @Nonnull Map scriptVariables ) throws TransformerException; + + @Nullable + DhisToFhirTransformOutcome transformCasted( @Nonnull DhisToFhirTransformerContext context, + @Nonnull ScriptedDhisResource input, @Nonnull AbstractRule rule, + @Nonnull Map scriptVariables ) throws TransformerException; +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerContextImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerContextImpl.java new file mode 100644 index 00000000..fa22bbe9 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerContextImpl.java @@ -0,0 +1,93 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl; + +/* + * Copyright (c) 2004-2018, 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.dhis2.fhir.adapter.fhir.metadata.model.RemoteSubscription; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.model.DhisRequest; + +import javax.annotation.Nonnull; +import java.io.Serializable; +import java.time.ZonedDateTime; + +/** + * Implementation of {@link DhisToFhirTransformerContext}. + * + * @author volsch + */ +public class DhisToFhirTransformerContextImpl implements DhisToFhirTransformerContext, Serializable +{ + private static final long serialVersionUID = -3205126998737677714L; + + private final DhisRequest dhisRequest; + + private final RemoteSubscription remoteSubscription; + + public DhisToFhirTransformerContextImpl( @Nonnull DhisRequest dhisRequest, @Nonnull RemoteSubscription remoteSubscription ) + { + this.dhisRequest = dhisRequest; + this.remoteSubscription = remoteSubscription; + } + + @Nonnull + @Override + public DhisRequest getDhisRequest() + { + return dhisRequest; + } + + @Nonnull + @Override + public FhirVersion getVersion() + { + return remoteSubscription.getFhirVersion(); + } + + @Nonnull + @Override + public String getRemoteSubscriptionCode() + { + return remoteSubscription.getCode(); + } + + @Nonnull + @Override + public ZonedDateTime now() + { + return ZonedDateTime.now(); + } + + @Override + public void fail( @Nonnull String message ) throws TransformerDataException + { + throw new TransformerDataException( message ); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerRequestImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerRequestImpl.java new file mode 100644 index 00000000..b5559389 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerRequestImpl.java @@ -0,0 +1,114 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl; + +/* + * Copyright (c) 2004-2018, 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.dhis2.fhir.adapter.fhir.metadata.model.AbstractRule; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerRequest; +import org.dhis2.fhir.adapter.fhir.transform.dhis.util.DhisToFhirTransformerUtils; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedDhisResource; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; + +/** + * Implementation of {@link DhisToFhirTransformerRequest}. + * + * @author volsch + */ +public class DhisToFhirTransformerRequestImpl implements DhisToFhirTransformerRequest +{ + private static final long serialVersionUID = 4181923310602004074L; + + private final DhisToFhirTransformerContext context; + + private final ScriptedDhisResource input; + + private final Map transformerUtils; + + private final List rules; + + private int ruleIndex; + + public DhisToFhirTransformerRequestImpl( @Nonnull DhisToFhirTransformerContext context, @Nonnull ScriptedDhisResource input, @Nonnull Map transformerUtils, @Nonnull List rules ) + { + this.context = context; + this.input = input; + this.transformerUtils = transformerUtils; + this.rules = rules; + } + + @Nonnull + @Override + public DhisToFhirTransformerContext getContext() + { + return context; + } + + @Nonnull + @Override + public ScriptedDhisResource getInput() + { + return input; + } + + @Nonnull + public Map getTransformerUtils() + { + return transformerUtils; + } + + @Nonnull + public List getRules() + { + return rules; + } + + public boolean isFirstRule() + { + return (ruleIndex == 0); + } + + public boolean isLastRule() + { + return (ruleIndex >= rules.size()); + } + + @Nullable + public AbstractRule nextRule() + { + if ( ruleIndex >= rules.size() ) + { + return null; + } + return rules.get( ruleIndex++ ); + } +} 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 new file mode 100644 index 00000000..17fa8cfb --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/impl/DhisToFhirTransformerServiceImpl.java @@ -0,0 +1,203 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.impl; + +/* + * Copyright (c) 2004-2018, 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.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.RemoteSubscription; +import org.dhis2.fhir.adapter.fhir.metadata.model.ScriptVariable; +import org.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.model.FhirVersionedValue; +import org.dhis2.fhir.adapter.fhir.script.ScriptExecutor; +import org.dhis2.fhir.adapter.fhir.transform.TransformerException; +import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformOutcome; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerContext; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerRequest; +import org.dhis2.fhir.adapter.fhir.transform.dhis.DhisToFhirTransformerService; +import org.dhis2.fhir.adapter.fhir.transform.dhis.model.DhisRequest; +import org.dhis2.fhir.adapter.fhir.transform.dhis.util.DhisToFhirTransformerUtils; +import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedDhisResource; +import org.dhis2.fhir.adapter.lock.LockContext; +import org.dhis2.fhir.adapter.lock.LockManager; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.stereotype.Service; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Implementation of {@link DhisToFhirTransformerService}. + * + * @author volsch + */ +@Service +public class DhisToFhirTransformerServiceImpl implements DhisToFhirTransformerService +{ + private final Logger logger = LoggerFactory.getLogger( getClass() ); + + private final LockManager lockManager; + + private final Map ruleResolvers = new HashMap<>(); + + private final Map, DhisToFhirTransformer> transformers = new HashMap<>(); + + private final Map> transformerUtils = new HashMap<>(); + + private final ScriptExecutor scriptExecutor; + + public DhisToFhirTransformerServiceImpl( @Nonnull LockManager lockManager, + @Nonnull ObjectProvider> ruleResolvers, + @Nonnull ObjectProvider>> transformersProvider, + @Nonnull ObjectProvider> transformUtilsProvider, + @Nonnull ScriptExecutor scriptExecutor ) + { + this.lockManager = lockManager; + this.scriptExecutor = scriptExecutor; + + ruleResolvers.ifAvailable( resolvers -> + resolvers.forEach( r -> this.ruleResolvers.put( r.getDhisResourceType(), r ) ) ); + transformersProvider.ifAvailable( transformers -> + { + for ( final DhisToFhirTransformer transformer : transformers ) + { + for ( final FhirVersion fhirVersion : transformer.getFhirVersions() ) + { + this.transformers.put( new FhirVersionedValue<>( fhirVersion, transformer.getDhisResourceType() ), transformer ); + } + } + } ); + transformUtilsProvider.ifAvailable( dhisToFhirTransformerUtils -> + { + for ( final DhisToFhirTransformerUtils tu : dhisToFhirTransformerUtils ) + { + for ( final FhirVersion fhirVersion : tu.getFhirVersions() ) + { + this.transformerUtils.computeIfAbsent( fhirVersion, key -> new HashMap<>() ).put( tu.getScriptAttrName(), tu ); + } + } + } ); + } + + @Nullable + @Override + public DhisToFhirTransformerRequest createTransformerRequest( @Nonnull DhisRequest dhisRequest, @Nonnull DhisResource originalInput ) + { + final DhisResource input = Objects.requireNonNull( DhisBeanTransformerUtils.clone( originalInput ) ); + + final DhisToFhirRuleResolver ruleResolver = ruleResolvers.get( dhisRequest.getResourceType() ); + if ( ruleResolver == null ) + { + throw new TransformerMappingException( "No rule resolver can be found for DHIS resource type " + dhisRequest.getResourceType() ); + } + final List rules = ruleResolver.resolveRule( input ); + if ( rules.isEmpty() ) + { + logger.info( "Could not find any rule to process DHIS resource." ); + return null; + } + + final RemoteSubscription remoteSubscription = ruleResolver.resolveRemoteSubscription( input, rules ); + if ( remoteSubscription == null ) + { + logger.info( "Could not determine remote subscription to process DHIS resource." ); + return null; + } + + final Map transformerUtils = this.transformerUtils.get( remoteSubscription.getFhirVersion() ); + if ( transformerUtils == null ) + { + throw new TransformerMappingException( "No transformer utils can be found for FHIR version " + remoteSubscription.getFhirVersion() ); + } + + return new DhisToFhirTransformerRequestImpl( new DhisToFhirTransformerContextImpl( dhisRequest, remoteSubscription ), + ruleResolver.convert( input ), transformerUtils, rules ); + } + + @Nullable + @Override + public DhisToFhirTransformOutcome transform( @Nonnull DhisToFhirTransformerRequest transformerRequest ) throws TransformerException + { + final DhisToFhirTransformerRequestImpl transformerRequestImpl = (DhisToFhirTransformerRequestImpl) transformerRequest; + + final boolean firstRule = transformerRequestImpl.isFirstRule(); + AbstractRule rule; + while ( (rule = transformerRequestImpl.nextRule()) != null ) + { + final DhisToFhirTransformer transformer = this.transformers.get( + new FhirVersionedValue<>( transformerRequestImpl.getContext().getVersion(), rule.getDhisResourceType() ) ); + if ( transformer == null ) + { + throw new TransformerMappingException( "No transformer can be found for FHIR version " + + transformerRequestImpl.getContext().getVersion() + + " mapping of DHIS resource type " + rule.getDhisResourceType() ); + } + + final Map scriptVariables = new HashMap<>( transformerRequestImpl.getTransformerUtils() ); + scriptVariables.put( ScriptVariable.CONTEXT.getVariableName(), transformerRequestImpl.getContext() ); + scriptVariables.put( ScriptVariable.INPUT.getVariableName(), transformerRequestImpl.getInput() ); + if ( isApplicable( transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), rule, scriptVariables ) ) + { + final DhisToFhirTransformOutcome outcome = transformer.transformCasted( + transformerRequestImpl.getContext(), transformerRequestImpl.getInput(), rule, scriptVariables ); + if ( outcome != null ) + { + logger.info( "Rule {} used successfully for transformation of {}.", + rule, transformerRequestImpl.getInput().getResourceId() ); + 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 ( firstRule ) + { + logger.info( "No matching rule for {}.", transformerRequestImpl.getInput().getResourceId() ); + } + return null; + } + + private boolean isApplicable( @Nonnull DhisToFhirTransformerContext context, @Nonnull ScriptedDhisResource input, + @Nonnull AbstractRule rule, @Nonnull Map scriptVariables ) throws TransformerException + { + if ( rule.getApplicableOutScript() == null ) + { + return true; + } + return Boolean.TRUE.equals( scriptExecutor.execute( rule.getApplicableOutScript(), context.getVersion(), scriptVariables, Boolean.class ) ); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/util/DhisToFhirTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/util/DhisToFhirTransformerUtils.java new file mode 100644 index 00000000..81a04089 --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/dhis/util/DhisToFhirTransformerUtils.java @@ -0,0 +1,50 @@ +package org.dhis2.fhir.adapter.fhir.transform.dhis.util; + +/* + * Copyright (c) 2004-2018, 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.dhis2.fhir.adapter.fhir.model.FhirVersion; +import org.dhis2.fhir.adapter.fhir.model.FhirVersionRestricted; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * Base interface for FHIR version restricted domain specific transformations + * utilities methods for DHIS 2 resource to FHIR resource transformations. + * + * @author volsch + */ +public interface DhisToFhirTransformerUtils extends FhirVersionRestricted +{ + @Nonnull + Set getFhirVersions(); + + @Nonnull + String getScriptAttrName(); +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/FhirToDhisTransformerContext.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/FhirToDhisTransformerContext.java index 721fb360..d1006c7c 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/FhirToDhisTransformerContext.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/FhirToDhisTransformerContext.java @@ -31,8 +31,8 @@ import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.model.ReferenceType; import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.FhirRequest; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import org.dhis2.fhir.adapter.scriptable.ScriptMethod; import org.dhis2.fhir.adapter.scriptable.ScriptMethodArg; import org.dhis2.fhir.adapter.scriptable.ScriptType; 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 237a589b..3eac2f9d 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 @@ -70,6 +70,13 @@ import java.util.Optional; import java.util.Set; +/** + * Abstract base class for all transformers from FHIR to DHIS 2 resources. + * + * @param the concrete type of the FHIR resource. + * @param the concrete type of transformation rule that this transformer processes. + * @author volsch + */ public abstract class AbstractFhirToDhisTransformer implements FhirToDhisTransformer { protected final Logger logger = LoggerFactory.getLogger( getClass() ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerContextImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerContextImpl.java index 06eae1c2..8099e4d7 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerContextImpl.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerContextImpl.java @@ -34,12 +34,18 @@ import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.FhirRequest; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.ImmutableFhirRequest; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.Serializable; import java.time.ZonedDateTime; +/** + * Implementation of {@link FhirToDhisTransformerContext}. + * + * @author volsch + */ public class FhirToDhisTransformerContextImpl implements FhirToDhisTransformerContext, Serializable { private static final long serialVersionUID = -3205126998737677714L; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerRequestImpl.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerRequestImpl.java index 4961c44b..b2d771e7 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerRequestImpl.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/FhirToDhisTransformerRequestImpl.java @@ -40,7 +40,7 @@ import java.util.Map; /** - * Implementation of {@link FhirToDhisTransformerContext}. + * Implementation of {@link FhirToDhisTransformerRequest}. * * @author volsch */ 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 11a73174..8861a102 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 @@ -46,7 +46,7 @@ import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerRequest; import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerService; import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.AbstractCodeFhirToDhisTransformerUtils; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.BeanTransformerUtils; +import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.FhirBeanTransformerUtils; import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.FhirToDhisTransformerUtils; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.FhirRequest; import org.dhis2.fhir.adapter.lock.LockContext; @@ -65,6 +65,11 @@ import java.util.Objects; import java.util.stream.Collectors; +/** + * Implementation of {@link FhirToDhisTransformerService}. + * + * @author volsch + */ @Service public class FhirToDhisTransformerServiceImpl implements FhirToDhisTransformerService { @@ -132,7 +137,7 @@ public FhirToDhisTransformerRequest createTransformerRequest( @Nonnull FhirReque final FhirContext fhirContext = remoteFhirResourceRepository.findFhirContext( fhirRequest.getVersion() ) .orElseThrow( () -> new FatalTransformerException( "FHIR context for FHIR version " + fhirRequest.getVersion() + " is not available." ) ); - final IBaseResource input = Objects.requireNonNull( BeanTransformerUtils.clone( fhirContext, originalInput ) ); + final IBaseResource input = Objects.requireNonNull( FhirBeanTransformerUtils.clone( fhirContext, originalInput ) ); final List rules = ruleRepository.findAllByInputData( fhirRequest.getResourceType(), codeTransformerUtils.getResourceCodes( input ) ) .stream().filter( r -> !contained || r.isContainedAllowed() ).collect( Collectors.toList() ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToDhisOptionSetUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToDhisOptionSetUtils.java index d196675d..520c4a74 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToDhisOptionSetUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/FhirToDhisOptionSetUtils.java @@ -30,7 +30,7 @@ import org.dhis2.fhir.adapter.dhis.model.Option; import org.dhis2.fhir.adapter.dhis.model.OptionSet; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -65,7 +65,7 @@ public static String getIntegerOptionCode( @Nullable String code, @Nullable Patt } if ( matcher.groupCount() != 1 ) { - throw new TransformerScriptException( "Pattern to resolve integer options must have exactly one group: " + pattern.pattern() ); + throw new TransformerScriptException( "Pattern to resolveRule integer options must have exactly one group: " + pattern.pattern() ); } return matcher.group( 1 ); } @@ -93,12 +93,12 @@ public static List resolveIntegerOptionCodes( @Nonnull OptionSet optionS { if ( options.put( Integer.parseInt( value ), code ) != null ) { - throw new TransformerScriptException( "Pattern to resolve integer options results in duplicate integer value " + value + ": " + resultingPattern.pattern() ); + throw new TransformerScriptException( "Pattern to resolveRule integer options results in duplicate integer value " + value + ": " + resultingPattern.pattern() ); } } catch ( NumberFormatException e ) { - throw new TransformerScriptException( "Pattern to resolve integer options results in non-integer value \"" + value + "\": " + resultingPattern.pattern() ); + throw new TransformerScriptException( "Pattern to resolveRule integer options results in non-integer value \"" + value + "\": " + resultingPattern.pattern() ); } } } @@ -111,7 +111,7 @@ private static void validateAscendingIntegerOptions( @Nonnull SortedMap createScriptedProgramStageEvents( @Nonnull protected boolean initAndValidateTrackedEntity( @Nonnull Program program, @Nonnull Map variables ) { - final ScriptedTrackedEntityInstance trackedEntityInstance = getScriptVariable( variables, ScriptVariable.TRACKED_ENTITY_INSTANCE, ScriptedTrackedEntityInstance.class ); + final WritableScriptedTrackedEntityInstance trackedEntityInstance = getScriptVariable( variables, ScriptVariable.TRACKED_ENTITY_INSTANCE, WritableScriptedTrackedEntityInstance.class ); for ( final ProgramTrackedEntityAttribute attribute : program.getTrackedEntityAttributes() ) { trackedEntityInstance.initValue( Reference.createIdReference( attribute.getAttributeId() ) ); diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractCodeFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractCodeFhirToDhisTransformerUtils.java index 5a36f995..b7f6a7d7 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractCodeFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractCodeFhirToDhisTransformerUtils.java @@ -41,8 +41,8 @@ import org.dhis2.fhir.adapter.fhir.transform.TransformerException; import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.ResourceSystem; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import org.dhis2.fhir.adapter.scriptable.ScriptMethod; import org.dhis2.fhir.adapter.scriptable.ScriptMethodArg; import org.dhis2.fhir.adapter.scriptable.ScriptType; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractDateTimeFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractDateTimeFhirToDhisTransformerUtils.java index a56243d9..66f88330 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractDateTimeFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractDateTimeFhirToDhisTransformerUtils.java @@ -29,7 +29,7 @@ */ import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import org.dhis2.fhir.adapter.model.DateUnit; import org.dhis2.fhir.adapter.scriptable.ScriptMethod; import org.dhis2.fhir.adapter.scriptable.ScriptMethodArg; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirToDhisTransformerUtils.java index cc90c814..b699d97b 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractFhirToDhisTransformerUtils.java @@ -31,7 +31,7 @@ import org.dhis2.fhir.adapter.fhir.model.FhirVersion; import org.dhis2.fhir.adapter.fhir.script.ScriptExecution; import org.dhis2.fhir.adapter.fhir.script.ScriptExecutionContext; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import javax.annotation.Nonnull; import java.util.Arrays; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractIdentifierFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractIdentifierFhirToDhisTransformerUtils.java index 23a7d522..2ec7c803 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractIdentifierFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractIdentifierFhirToDhisTransformerUtils.java @@ -35,8 +35,8 @@ import org.dhis2.fhir.adapter.fhir.transform.TransformerException; import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; import org.dhis2.fhir.adapter.fhir.transform.fhir.model.ResourceSystem; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import org.dhis2.fhir.adapter.scriptable.ScriptMethod; import org.dhis2.fhir.adapter.scriptable.ScriptMethodArg; import org.dhis2.fhir.adapter.scriptable.ScriptType; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractOrganizationFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractOrganizationFhirToDhisTransformerUtils.java index 48aa0b91..222a1ef9 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractOrganizationFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/AbstractOrganizationFhirToDhisTransformerUtils.java @@ -212,7 +212,7 @@ protected List findHierarchy( @Nullable IBaseReference final IBaseBundle hierarchyBundle = remoteHierarchicallyFhirResourceRepository.findWithParents( remoteSubscription.getId(), remoteSubscription.getFhirVersion(), remoteSubscription.getFhirEndpoint(), FhirResourceType.ORGANIZATION.getResourceTypeName(), childReference.getReferenceElement().getIdPart(), "organizationPartOf", this::getParentReference ); final List hierarchy = extractResources( hierarchyBundle ); - return hierarchy.isEmpty() ? null : BeanTransformerUtils.clone( fhirContext, hierarchy ); + return hierarchy.isEmpty() ? null : FhirBeanTransformerUtils.clone( fhirContext, hierarchy ); } @Nullable diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/BeanTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/FhirBeanTransformerUtils.java similarity index 97% rename from fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/BeanTransformerUtils.java rename to fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/FhirBeanTransformerUtils.java index 9752c967..80dcb66d 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/BeanTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/FhirBeanTransformerUtils.java @@ -44,7 +44,7 @@ * * @author volsch */ -public abstract class BeanTransformerUtils +public abstract class FhirBeanTransformerUtils { @Nullable @SuppressWarnings( { "unchecked" } ) @@ -72,7 +72,7 @@ public static List clone( @Nonnull FhirContext fhir return objects.stream().map( o -> clone( fhirContext, o ) ).collect( Collectors.toList() ); } - private BeanTransformerUtils() + private FhirBeanTransformerUtils() { super(); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/FhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/FhirToDhisTransformerUtils.java index ddb10430..a21fa678 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/FhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/FhirToDhisTransformerUtils.java @@ -34,6 +34,12 @@ import javax.annotation.Nonnull; import java.util.Set; +/** + * Base interface for FHIR version restricted domain specific transformations + * utilities methods for FHIR resource to DHIS 2 resource transformations. + * + * @author volsch + */ public interface FhirToDhisTransformerUtils extends FhirVersionRestricted { @Nonnull diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java index d38e6272..11003f78 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/util/ReferenceFhirToDhisTransformerUtils.java @@ -41,7 +41,7 @@ import org.dhis2.fhir.adapter.fhir.transform.TransformerDataException; import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; +import org.dhis2.fhir.adapter.fhir.transform.scripted.TransformerScriptException; import org.dhis2.fhir.adapter.scriptable.ScriptMethod; import org.dhis2.fhir.adapter.scriptable.ScriptMethodArg; import org.dhis2.fhir.adapter.scriptable.ScriptType; @@ -66,7 +66,7 @@ @Component @Scriptable @ScriptType( value = "ReferenceUtils", var = ReferenceFhirToDhisTransformerUtils.SCRIPT_ATTR_NAME, - description = "Utilities to resolve FHIR Reference to FHIR Resources when handling FHIR to DHIS2 transformations." ) + description = "Utilities to resolveRule FHIR Reference to FHIR Resources when handling FHIR to DHIS2 transformations." ) public class ReferenceFhirToDhisTransformerUtils extends AbstractFhirToDhisTransformerUtils { public static final String SCRIPT_ATTR_NAME = "referenceUtils"; @@ -215,7 +215,7 @@ public IBaseResource getResource( @Nullable IBaseReference reference, @Nullable finalResourceType, reference.getReferenceElement().getIdPart() ) : remoteFhirResourceRepository.find( remoteSubscription.getId(), remoteSubscription.getFhirVersion(), remoteSubscription.getFhirEndpoint(), finalResourceType, reference.getReferenceElement().getIdPart() ); - final IBaseResource resource = optionalResource.map( r -> BeanTransformerUtils.clone( fhirContext, r ) ) + final IBaseResource resource = optionalResource.map( r -> FhirBeanTransformerUtils.clone( fhirContext, r ) ) .orElseThrow( () -> new TransformerDataException( "Referenced FHIR resource " + reference.getReferenceElement() + " does not exist for remote subscription resource " + resourceId ) ); reference.setResource( resource ); return resource; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/ImmutableScriptedEnrollment.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEnrollment.java similarity index 91% rename from fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/ImmutableScriptedEnrollment.java rename to fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEnrollment.java index a854e846..2d7fd63d 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/ImmutableScriptedEnrollment.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEnrollment.java @@ -1,4 +1,4 @@ -package org.dhis2.fhir.adapter.fhir.transform.fhir.impl.program; +package org.dhis2.fhir.adapter.fhir.transform.scripted; /* * Copyright (c) 2004-2018, University of Oslo @@ -28,8 +28,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.fhir.transform.TransformerException; -import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedEnrollment; import org.dhis2.fhir.adapter.geo.Location; import org.dhis2.fhir.adapter.scriptable.Scriptable; @@ -38,6 +38,11 @@ import java.io.Serializable; import java.time.ZonedDateTime; +/** + * Immutable scripted enrollment. + * + * @author volsch + */ @Scriptable public class ImmutableScriptedEnrollment implements ScriptedEnrollment, Serializable { @@ -63,6 +68,13 @@ public String getId() return delegate.getId(); } + @Nullable + @Override + public DhisResourceId getResourceId() + { + return delegate.getResourceId(); + } + @Nullable @Override public ZonedDateTime getLastUpdated() diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/ImmutableScriptedEvent.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEvent.java similarity index 91% rename from fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/ImmutableScriptedEvent.java rename to fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEvent.java index 3131e57d..b8304ad5 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/program/ImmutableScriptedEvent.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedEvent.java @@ -1,4 +1,4 @@ -package org.dhis2.fhir.adapter.fhir.transform.fhir.impl.program; +package org.dhis2.fhir.adapter.fhir.transform.scripted; /* * Copyright (c) 2004-2018, University of Oslo @@ -29,9 +29,9 @@ */ +import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.dhis.tracker.program.EventStatus; import org.dhis2.fhir.adapter.fhir.transform.TransformerException; -import org.dhis2.fhir.adapter.fhir.transform.scripted.ScriptedEvent; import org.dhis2.fhir.adapter.geo.Location; import org.dhis2.fhir.adapter.scriptable.Scriptable; @@ -40,6 +40,11 @@ import java.io.Serializable; import java.time.ZonedDateTime; +/** + * Immutable scripted event. + * + * @author volsch + */ @Scriptable public class ImmutableScriptedEvent implements ScriptedEvent, Serializable { @@ -65,6 +70,13 @@ public String getId() return delegate.getId(); } + @Nullable + @Override + public DhisResourceId getResourceId() + { + return delegate.getResourceId(); + } + @Nullable @Override public ZonedDateTime getLastUpdated() diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedTrackedEntityInstance.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedTrackedEntityInstance.java new file mode 100644 index 00000000..3252b1ce --- /dev/null +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ImmutableScriptedTrackedEntityInstance.java @@ -0,0 +1,113 @@ +package org.dhis2.fhir.adapter.fhir.transform.scripted; + +/* + * Copyright (c) 2004-2018, 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.dhis2.fhir.adapter.dhis.model.DhisResourceId; +import org.dhis2.fhir.adapter.dhis.model.Reference; +import org.dhis2.fhir.adapter.fhir.transform.TransformerException; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.time.ZonedDateTime; + +/** + * Immutable scripted tracked entity instance. + * + * @author volsch + */ +public class ImmutableScriptedTrackedEntityInstance implements ScriptedTrackedEntityInstance +{ + private final ScriptedTrackedEntityInstance delegate; + + public ImmutableScriptedTrackedEntityInstance( @Nonnull ScriptedTrackedEntityInstance delegate ) + { + this.delegate = delegate; + } + + @Override + @Nonnull + public String getTypeId() + { + return delegate.getTypeId(); + } + + @Override + @Nullable + public String getCoordinates() + { + return delegate.getCoordinates(); + } + + @Override + @Nullable + public Object getValue( @Nonnull Reference attributeReference ) + { + return delegate.getValue( attributeReference ); + } + + @Override + @Nullable + public String getId() + { + return delegate.getId(); + } + + @Nullable + @Override + public DhisResourceId getResourceId() + { + return delegate.getResourceId(); + } + + @Override + public boolean isNewResource() + { + return delegate.isNewResource(); + } + + @Override + @Nullable + public ZonedDateTime getLastUpdated() + { + return delegate.getLastUpdated(); + } + + @Override + @Nullable + public String getOrganizationUnitId() + { + return delegate.getOrganizationUnitId(); + } + + @Override + public void validate() throws TransformerException + { + delegate.validate(); + } +} diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedDhisResource.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedDhisResource.java index 58987255..6fc6330b 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedDhisResource.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedDhisResource.java @@ -28,6 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.fhir.transform.TransformerException; import org.dhis2.fhir.adapter.scriptable.Scriptable; @@ -45,6 +46,9 @@ public interface ScriptedDhisResource @Nullable String getId(); + @Nullable + DhisResourceId getResourceId(); + boolean isNewResource(); @Nullable diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedTrackedEntityInstance.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedTrackedEntityInstance.java index ac60036f..970f8576 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedTrackedEntityInstance.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/ScriptedTrackedEntityInstance.java @@ -50,6 +50,4 @@ public interface ScriptedTrackedEntityInstance extends ScriptedDhisResource @Nullable Object getValue( @Nonnull Reference attributeReference ); - - void initValue( @Nonnull Reference attributeReference ); } diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/TransformerScriptException.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/TransformerScriptException.java similarity index 93% rename from fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/TransformerScriptException.java rename to fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/TransformerScriptException.java index 6c28dff0..50df6d96 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/fhir/impl/TransformerScriptException.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/TransformerScriptException.java @@ -1,4 +1,4 @@ -package org.dhis2.fhir.adapter.fhir.transform.fhir.impl; +package org.dhis2.fhir.adapter.fhir.transform.scripted; /* * Copyright (c) 2004-2018, University of Oslo @@ -30,6 +30,11 @@ import org.dhis2.fhir.adapter.fhir.transform.TransformerException; +/** + * Thrown if a transformation script caused an exception. + * + * @author volsch + */ public class TransformerScriptException extends TransformerException { private static final long serialVersionUID = -1296515465059154893L; diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEnrollment.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEnrollment.java index d727806d..f43cbcf9 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEnrollment.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEnrollment.java @@ -29,6 +29,7 @@ */ import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.dhis.tracker.program.Enrollment; import org.dhis2.fhir.adapter.dhis.tracker.program.Program; import org.dhis2.fhir.adapter.fhir.transform.TransformerException; @@ -82,6 +83,13 @@ public String getId() return enrollment.getId(); } + @Nullable + @Override + public DhisResourceId getResourceId() + { + return enrollment.getResourceId(); + } + @Nullable @Override @ScriptMethod( description = "Returns the date and time when the resource has been updated the last time or null if this is a new resource." ) diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java index 5188b0b1..09c311be 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedEvent.java @@ -31,6 +31,7 @@ import org.dhis2.fhir.adapter.converter.ConversionException; import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.model.WritableDataValue; import org.dhis2.fhir.adapter.dhis.tracker.program.Event; @@ -40,7 +41,6 @@ import org.dhis2.fhir.adapter.fhir.transform.TransformerException; import org.dhis2.fhir.adapter.fhir.transform.TransformerMappingException; import org.dhis2.fhir.adapter.fhir.transform.fhir.FhirToDhisTransformerContext; -import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.TransformerScriptException; import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.program.FhirToDhisOptionSetUtils; import org.dhis2.fhir.adapter.fhir.transform.fhir.impl.util.ScriptedDateTimeUtils; import org.dhis2.fhir.adapter.geo.Location; @@ -95,6 +95,13 @@ public String getId() return event.getId(); } + @Nullable + @Override + public DhisResourceId getResourceId() + { + return event.getResourceId(); + } + @Nullable @Override @ScriptMethod( description = "Returns the date and time when the resource has been updated the last time or null if this is a new resource." ) diff --git a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedTrackedEntityInstance.java b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedTrackedEntityInstance.java index e2302437..95771656 100644 --- a/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedTrackedEntityInstance.java +++ b/fhir/src/main/java/org/dhis2/fhir/adapter/fhir/transform/scripted/WritableScriptedTrackedEntityInstance.java @@ -30,6 +30,7 @@ import org.dhis2.fhir.adapter.converter.ConversionException; import org.dhis2.fhir.adapter.dhis.converter.ValueConverter; +import org.dhis2.fhir.adapter.dhis.model.DhisResourceId; import org.dhis2.fhir.adapter.dhis.model.Option; import org.dhis2.fhir.adapter.dhis.model.Reference; import org.dhis2.fhir.adapter.dhis.tracker.trackedentity.TrackedEntityAttribute; @@ -99,6 +100,13 @@ public String getId() return trackedEntityInstance.getId(); } + @Nullable + @Override + public DhisResourceId getResourceId() + { + return trackedEntityInstance.getResourceId(); + } + @Nullable @Override @ScriptMethod( description = "Returns the date and time when the resource has been updated the last time or null if this is a new resource." ) @@ -229,7 +237,6 @@ public boolean setOptionalValue( @Nullable Reference attributeReference, @Nullab return true; } - @Override public void initValue( @Nonnull Reference attributeReference ) { trackedEntityType.getOptionalTypeAttribute( attributeReference ).ifPresent( ta -> trackedEntityInstance.getAttribute( ta.getAttributeId() ) ); diff --git a/fhir/src/main/resources/db/migration/production/V1.1.0.0_0_0__TEI_Export.sql b/fhir/src/main/resources/db/migration/production/V1.1.0.0_0_0__TEI_Export.sql index 81268ed6..8c44561f 100644 --- a/fhir/src/main/resources/db/migration/production/V1.1.0.0_0_0__TEI_Export.sql +++ b/fhir/src/main/resources/db/migration/production/V1.1.0.0_0_0__TEI_Export.sql @@ -129,3 +129,26 @@ COMMENT ON TABLE fhir_queued_dhis_resource IS 'Contains queued DHIS2 resources t COMMENT ON COLUMN fhir_queued_dhis_resource.dhis_sync_group_id IS 'References the DHIS2 sync group to which this data belongs to.'; COMMENT ON COLUMN fhir_queued_dhis_resource.dhis_resource_id IS 'The ID (with resource name) of the DHIS2 Resource that has been queued.'; COMMENT ON COLUMN fhir_queued_dhis_resource.queued_at IS 'The timestamp when the data has been queued last time.'; + +ALTER TABLE fhir_rule + ADD in_enabled BOOLEAN DEFAULT TRUE NOT NULL, + ADD out_enabled BOOLEAN DEFAULT FALSE NOT NULL; +COMMENT ON COLUMN fhir_rule.in_enabled IS 'Specifies if transformation from FHIR to DHIS resource is enabled.'; +COMMENT ON COLUMN fhir_rule.out_enabled IS 'Specifies if transformation from DHIS to FHIR resource is enabled.'; + +ALTER TABLE fhir_rule + ADD COLUMN applicable_out_script_id UUID, + ADD CONSTRAINT fhir_rule_fk6 FOREIGN KEY (applicable_out_script_id) REFERENCES fhir_executable_script (id); +CREATE INDEX fhir_rule_i4 + ON fhir_rule (applicable_out_script_id); +COMMENT ON COLUMN fhir_rule.applicable_out_script_id IS 'References the evaluation script that is used to evaluate if the DHIS 2 resource is applicable to be processed by this rule. If no script has been specified, the rule is applicable for further processing.'; + +ALTER TABLE fhir_rule + ADD COLUMN transform_out_script_id UUID, + ADD CONSTRAINT fhir_rule_fk6 FOREIGN KEY (transform_out_script_id) REFERENCES fhir_executable_script (id); +CREATE INDEX fhir_rule_i5 + ON fhir_rule (transform_out_script_id); +COMMENT ON COLUMN fhir_rule.transform_out_script_id IS 'References the transformation script that is used to transform the DHIS 2 resource to the FHIR resource.'; + +ALTER TABLE fhir_rule + ALTER COLUMN transform_in_script_id DROP NOT NULL; diff --git a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/RuleRepositoryRestDocsTest.java b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/RuleRepositoryRestDocsTest.java index ab5d0af9..9d44543f 100644 --- a/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/RuleRepositoryRestDocsTest.java +++ b/fhir/src/test/java/org/dhis2/fhir/adapter/fhir/metadata/repository/RuleRepositoryRestDocsTest.java @@ -93,11 +93,16 @@ public void createTrackedEntityRule() throws Exception fields.withPath( "dhisResourceType" ).description( "The type of the rule and the type of the data that is stored in DHIS2." ).type( JsonFieldType.STRING ), fields.withPath( "fhirResourceType" ).description( "The FHIR resource type of the incoming resource." ).type( JsonFieldType.STRING ), fields.withPath( "enabled" ).description( "Specifies if this rule is enabled." ).type( JsonFieldType.BOOLEAN ), + fields.withPath( "inEnabled" ).description( "Specifies if transformation of a FHIR to a DHIS2 resource has been enabled (by default true)." ).type( JsonFieldType.BOOLEAN ).optional(), + fields.withPath( "outEnabled" ).description( "Specifies if transformation of a DHIS2 to a FHIR resource has been enabled (by default false)." ).type( JsonFieldType.BOOLEAN ).optional(), fields.withPath( "evaluationOrder" ).description( "Specifies the precedence of this rule when several rules match. Higher values define a higher precedence." ).type( JsonFieldType.NUMBER ), fields.withPath( "applicableCodeSet" ).description( "Link to the code set reference that is used to check if the incoming request is applicable for this rule." ).type( JsonFieldType.STRING ).optional(), - fields.withPath( "applicableInScript" ).description( "Link to the executable script reference that is used to check if the incoming request is applicable for this rule. " + + fields.withPath( "applicableInScript" ).description( "Link to the executable script reference that is used to check if the incoming request is applicable for this rule when transforming from a FHIR to a DHIS2 resource. " + "The script must be an evaluation script that returns a boolean value." ).type( JsonFieldType.STRING ).optional(), - fields.withPath( "transformInScript" ).description( "Link to the executable script reference that is used to transform the FHIR resource input to the DHIS2 resource." ).type( JsonFieldType.STRING ), + fields.withPath( "transformInScript" ).description( "Link to the executable script reference that is used to transform the FHIR resource input to the DHIS2 resource." ).type( JsonFieldType.STRING ).optional(), + fields.withPath( "applicableOutScript" ).description( "Link to the executable script reference that is used to check if the incoming request is applicable for this rule when transforming from a DHIS2 to a FHIR resource. " + + "The script must be an evaluation script that returns a boolean value." ).type( JsonFieldType.STRING ).optional(), + fields.withPath( "transformOutScript" ).description( "Link to the executable script reference that is used to transform the DHIS2 resource input to the FHIR resource." ).type( JsonFieldType.STRING ).optional(), fields.withPath( "trackedEntity" ).description( "The reference to the DHIS2 Tracked Entity resource." ).type( JsonFieldType.STRING ), fields.withPath( "orgUnitLookupScript" ).description( "Link to the executable script reference that is used to extract the organization unit reference. " + "The script must be an evaluation script that return a reference." ).type( JsonFieldType.STRING ), @@ -132,7 +137,10 @@ public void readTrackedEntityRule() throws Exception linkWithRel( "trackedEntityRule" ).description( "Link to this resource itself." ), 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( "applicableInScript" ).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( "transformInScript" ).description( "Link to the executable script reference that is used to transform the FHIR resource input to the DHIS2 resource." ), + linkWithRel( "transformInScript" ).description( "Link to the executable script reference that is used to transform the FHIR resource input to the DHIS2 resource." ).optional(), + linkWithRel( "applicableOutScript" ).description( "Link to the executable script reference that is used to check if the incoming request is applicable for this rule when transforming a DHIS2 to FHIR resource. " + + "The script must be an evaluation script that returns a boolean value." ).optional(), + linkWithRel( "transformOutScript" ).description( "Link to the executable script reference that is used to transform the DHIS2 resource input to the FHIR resource." ).optional(), linkWithRel( "trackedEntity" ).description( "Link to the tracked entity resource that describes the tracked entity of the transformation." ), linkWithRel( "orgUnitLookupScript" ).description( "Link to the executable script reference that is used to extract the organization unit reference. The script must be an evaluation script that return a reference." ).optional(), linkWithRel( "locationLookupScript" ).description( "Link to the executable script reference that is used to extract the location reference. The script must be an evaluation script that return a location (geo coordinates)." ).optional(), @@ -147,6 +155,8 @@ public void readTrackedEntityRule() throws Exception fields.withPath( "dhisResourceType" ).description( "The type of the rule and the type of the data that is stored in DHIS2." ).type( JsonFieldType.STRING ), fields.withPath( "fhirResourceType" ).description( "The FHIR resource type of the incoming resource." ).type( JsonFieldType.STRING ), fields.withPath( "enabled" ).description( "Specifies if this rule is enabled." ).type( JsonFieldType.BOOLEAN ), + fields.withPath( "inEnabled" ).description( "Specifies if transformation of a FHIR to a DHIS2 resource has been enabled." ).type( JsonFieldType.BOOLEAN ), + fields.withPath( "outEnabled" ).description( "Specifies if transformation of a DHIS2 to a FHIR resource has been enabled." ).type( JsonFieldType.BOOLEAN ), fields.withPath( "evaluationOrder" ).description( "Specifies the precedence of this rule when several rules match. Higher values define a higher precedence." ).type( JsonFieldType.NUMBER ), fields.withPath( "containedAllowed" ).description( "Specified if this rule can process contained resources." ).type( JsonFieldType.BOOLEAN ).optional(), subsectionWithPath( "_links" ).description( "Links to other resources" ) @@ -167,7 +177,7 @@ protected AbstractRule loadTrackedEntityRule( @Nonnull String name ) { final AbstractRule example = new TrackedEntityRule(); example.setName( name ); - return ruleRepository.findOne( Example.of( example, ExampleMatcher.matching().withIgnorePaths( "enabled", "evaluationOrder" ) ) ) + return ruleRepository.findOne( Example.of( example, ExampleMatcher.matching().withIgnorePaths( "enabled", "evaluationOrder", "inEnabled", "outEnabled" ) ) ) .orElseThrow( () -> new AssertionError( "Rule does not exist: " + name ) ); }