Skip to content

Commit

Permalink
Added more documentation for REST interfaces.
Browse files Browse the repository at this point in the history
  • Loading branch information
volsch committed Nov 13, 2018
1 parent dfcf16a commit a23bf5a
Show file tree
Hide file tree
Showing 72 changed files with 2,412 additions and 137 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This repository contains the source code of the DHIS2 FHIR Adapter. The current scope of the Adapter is to import data into DHIS2 Tracker by using FHIR Subscriptions. Event if the adapter may support more FHIR Resource types at the moment, the initial
official support is for FHIR Patient resources that are transformed to DHIS2 Tracked Entity instances.

The import works on the basis of a domain specific business rule engine that decides about transformations of medical data to questionnaire-like structures (DHIS2 Tracker Programs and their Program Stages).
The import works on the basis of a domain specific business rule engine that decides about transformations of patient related medical data to questionnaire-like structures (DHIS2 Tracker Programs and their Program Stages).

![DHIS2 FHIR Adapter High Level Architecture](docs/images/DHIS2_FHIR_Adapter_High_Level_Architecture.png "DHIS2 FHIR Adapter High Level Architecture")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
*/

import org.dhis2.fhir.adapter.fhir.metadata.model.SubscriptionAdapterEndpoint;
import org.dhis2.fhir.adapter.validator.HttpUrl;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.dhis2.fhir.adapter.fhir.metadata.model.RequestHeader;
import org.dhis2.fhir.adapter.fhir.metadata.model.SubscriptionFhirEndpoint;
import org.dhis2.fhir.adapter.fhir.metadata.model.SubscriptionType;
import org.dhis2.fhir.adapter.validator.HttpUrl;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import org.dhis2.fhir.adapter.fhir.metadata.model.RemoteSubscriptionSystem;
import org.dhis2.fhir.adapter.fhir.metadata.model.System;
import org.dhis2.fhir.adapter.validator.Uri;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.dhis2.fhir.adapter.jackson;
package org.dhis2.fhir.adapter.validator;

/*
* Copyright (c) 2004-2018, University of Oslo
Expand Down Expand Up @@ -28,41 +28,32 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.util.Converter;

import java.util.ArrayList;
import java.util.List;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Converts lists (especially persistent bag) to a list.
* This is required when class name is serialized and used sorted set class
* cannot be instantiated otherwise.
* Validation that a value is a supported value.
*
* @author volsch
*/
public class PersistentBagConverter implements Converter<List<?>, List<?>>
@Constraint( validatedBy = EnumValueValidator.class )
@Target( { ElementType.FIELD } )
@Retention( RetentionPolicy.RUNTIME )
public @interface EnumValue
{
@Override
public List<?> convert( List<?> value )
{
if ( value == null )
{
return null;
}
return new ArrayList<>( value );
}
String message() default "Supported enum values {value}, unsupported {unsupported}";

Class<? extends Enum<?>> value();

String[] unsupported() default {};

String[] supported() default {};

@Override
public JavaType getInputType( TypeFactory typeFactory )
{
return typeFactory.constructCollectionType( List.class, Object.class );
}
Class<?>[] groups() default {};

@Override
public JavaType getOutputType( TypeFactory typeFactory )
{
return typeFactory.constructCollectionType( ArrayList.class, Object.class );
}
}
Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package org.dhis2.fhir.adapter.validator;

/*
* 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.lang3.StringUtils;

import javax.annotation.Nonnull;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
* Validates that value is enumeration value. This is primarily used for documentation
* purpose (Spring REST Docs).
*
* @author volsch
*/
public class EnumValueValidator implements ConstraintValidator<EnumValue, Object>
{
private Set<Enum<?>> supported;

@SuppressWarnings( "unchecked" )
@Override
public void initialize( EnumValue enumValue )
{
supported = new HashSet<>( getSupported( enumValue.value(), enumValue.unsupported(), enumValue.supported() ) );
}

@SuppressWarnings( "unchecked" )
@Override
public boolean isValid( Object value, ConstraintValidatorContext context )
{
if ( value == null )
{
return true;
}

final Collection<Enum<?>> values;
if ( value instanceof Collection )
{
values = (Collection<Enum<?>>) value;
}
else
{
values = Collections.singleton( (Enum) value );
}

for ( final Enum<?> v : values )
{
if ( (v != null) && !supported.contains( v ) )
{
{
context.buildConstraintViolationWithTemplate( "Supported values " + StringUtils.join( supported, ", " ) );
return false;
}
}
}
return true;
}

@SuppressWarnings( "unchecked" )
@Nonnull
public static SortedSet<Enum<?>> getSupported( @Nonnull Class<? extends Enum<?>> enumClass, @Nonnull String[] unsupportedValues, @Nonnull String[] supportedValues )
{
final Set<Enum<?>> unsupported = new HashSet<>();
for ( final String value : unsupportedValues )
{
unsupported.add( Enum.valueOf( (Class<? extends Enum>) enumClass, value ) );
}
final SortedSet<Enum<?>> supported = new TreeSet<>( Comparator.comparing( Enum::name ) );
if ( supportedValues.length > 0 )
{
for ( final String value : supportedValues )
{
supported.add( Enum.valueOf( (Class<? extends Enum>) enumClass, value ) );
}
}
else
{
supported.addAll( Arrays.asList( enumClass.getEnumConstants() ) );
}
supported.removeAll( unsupported );
return supported;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.dhis2.fhir.adapter.setup;
package org.dhis2.fhir.adapter.validator;

/*
* Copyright (c) 2004-2018, University of Oslo
Expand Down Expand Up @@ -45,7 +45,7 @@
@Retention( RetentionPolicy.RUNTIME )
public @interface HttpUrl
{
String message() default "Not a valid HTTP/HTTPS URL.";
String message() default "Not a valid HTTP/HTTPS URL";

Class<?>[] groups() default {};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.dhis2.fhir.adapter.setup;
package org.dhis2.fhir.adapter.validator;

/*
* Copyright (c) 2004-2018, University of Oslo
Expand Down Expand Up @@ -55,13 +55,13 @@ public boolean isValid( String value, ConstraintValidatorContext context )
}
catch ( MalformedURLException e )
{
context.buildConstraintViolationWithTemplate( "Not a valid URL." );
context.buildConstraintViolationWithTemplate( "Not a valid URL" );
return false;
}

if ( !"http".equals( protocol ) && !"https".equals( protocol ) )
{
context.buildConstraintViolationWithTemplate( "URL must use protocol HTTP or HTTPS." );
context.buildConstraintViolationWithTemplate( "URL must use protocol HTTP or HTTPS" );
return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.dhis2.fhir.adapter.setup;
package org.dhis2.fhir.adapter.validator;

/*
* Copyright (c) 2004-2018, University of Oslo
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.dhis2.fhir.adapter.setup;
package org.dhis2.fhir.adapter.validator;

/*
* Copyright (c) 2004-2018, University of Oslo
Expand Down Expand Up @@ -54,7 +54,7 @@ public boolean isValid( String value, ConstraintValidatorContext context )
}
catch ( URISyntaxException e )
{
context.buildConstraintViolationWithTemplate( "Not a valid URI." );
context.buildConstraintViolationWithTemplate( "Not a valid URI" );
return false;
}

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public abstract class AbstractRule extends VersionedBaseMetadata implements Seri

private String name;
private String description;
private boolean enabled;
private boolean enabled = true;
private int evaluationOrder;
private DhisResourceType dhisResourceType;
private FhirResourceType fhirResourceType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
*/

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.rest.core.annotation.RestResource;

import javax.persistence.Basic;
import javax.persistence.Column;
Expand Down Expand Up @@ -98,7 +99,7 @@ public void setName( String name )
}

@Basic
@Column( name = "code", nullable = false, length = 50 )
@Column( name = "code", nullable = false, length = 50, unique = true )
public String getCode()
{
return code;
Expand Down Expand Up @@ -148,6 +149,7 @@ public void setCodeCategory( CodeCategory codeCategory )
@OneToMany( mappedBy = "code" )
@OrderBy( "id" )
@JsonIgnore
@RestResource( exported = false )
public List<SystemCode> getSystemCodes()
{
return systemCodes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public void setName( String name )
}

@Basic
@Column( name = "code", nullable = false, length = 50 )
@Column( name = "code", nullable = false, length = 50, unique = true )
public String getCode()
{
return code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
import java.util.Objects;
import java.util.SortedSet;

/**
* Contains a collection of {@linkplain Code code}. E.g. there may be multiple codes
* for vaccines that cause an immunization for measles.
*
* @author volsch
*/
@Entity
@Table( name = "fhir_code_set" )
public class CodeSet extends VersionedBaseMetadata implements Serializable
Expand All @@ -67,7 +73,7 @@ public void setName( String name )
}

@Basic
@Column( name = "code", nullable = false, length = 50 )
@Column( name = "code", nullable = false, length = 50, unique = true )
public String getCode()
{
return code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
import java.io.Serializable;
import java.util.Objects;

/**
* Contains the value of the {@linkplain CodeSet code set} which can additionally be
* enabled and disabled.
*
* @author volsch
*/
@Entity
@Table( name = "fhir_code_set_value" )
public class CodeSetValue implements Serializable, Comparable<CodeSetValue>, FhirAdapterMetadata<CodeSetValueId>
Expand All @@ -48,7 +54,7 @@ public class CodeSetValue implements Serializable, Comparable<CodeSetValue>, Fhi

private CodeSetValueId id;

private boolean enabled;
private boolean enabled = true;

@EmbeddedId
public CodeSetValueId getId()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
import java.io.Serializable;
import java.util.Objects;

/**
* Contains the ID of a value of the {@linkplain CodeSet code set} which can additionally
* be enabled and disabled. This is just a single assigned code.
*
* @author volsch
*/
@Embeddable
public class CodeSetValueId implements Serializable
{
Expand Down
Loading

0 comments on commit a23bf5a

Please sign in to comment.