CMSgov/dpc-app

View on GitHub
dpc-api/src/main/java/gov/cms/dpc/api/resources/v1/EndpointResource.java

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
package gov.cms.dpc.api.resources.v1;

import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import com.codahale.metrics.annotation.ExceptionMetered;
import com.codahale.metrics.annotation.Timed;
import com.google.inject.name.Named;
import gov.cms.dpc.api.auth.OrganizationPrincipal;
import gov.cms.dpc.api.auth.annotations.Authorizer;
import gov.cms.dpc.api.auth.annotations.PathAuthorizer;
import gov.cms.dpc.api.resources.AbstractEndpointResource;
import gov.cms.dpc.fhir.DPCResourceType;
import gov.cms.dpc.fhir.annotations.FHIR;
import gov.cms.dpc.fhir.annotations.Profiled;
import gov.cms.dpc.fhir.helpers.FHIRHelpers;
import io.dropwizard.auth.Auth;
import io.swagger.annotations.*;
import org.eclipse.jetty.http.HttpStatus;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Endpoint;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Reference;

import javax.inject.Inject;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.util.UUID;

@Api(value = "Endpoint", authorizations = @Authorization(value = "access_token"))
@Path("/v1/Endpoint")
public class EndpointResource extends AbstractEndpointResource {

    private final IGenericClient client;

    @Inject
    EndpointResource(@Named("attribution") IGenericClient client) {
        this.client = client;
    }

    @POST
    @FHIR
    @Timed
    @ExceptionMetered
    @Authorizer
    @ApiOperation(value = "Create an Endpoint", notes = "Create an Endpoint resource for an Organization")
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "Endpoint created"),
            @ApiResponse(code = 400, message = "Bad request"),
            @ApiResponse(code = 422, message = "Endpoint not valid")
    })
    @Override
    public Response createEndpoint(@ApiParam(hidden = true) @Auth OrganizationPrincipal organizationPrincipal,
                                   @ApiParam @Valid @Profiled Endpoint endpoint) {
        Reference organizationPrincipalRef = new Reference(new IdType("Organization", organizationPrincipal.getID().toString()));
        if (endpoint.hasManagingOrganization() && !endpoint.getManagingOrganization().getReference().equals(organizationPrincipalRef.getReference())) {
            throw new WebApplicationException("An Endpoint cannot be created for a different Organization", HttpStatus.UNPROCESSABLE_ENTITY_422);
        }

        endpoint.setManagingOrganization(new Reference(new IdType("Organization", organizationPrincipal.getID().toString())));
        MethodOutcome outcome = this.client
                .create()
                .resource(endpoint)
                .encodedJson()
                .execute();

        return FHIRHelpers.handleMethodOutcome(outcome);
    }

    @GET
    @FHIR
    @Timed
    @ExceptionMetered
    @Authorizer
    @ApiOperation(value = "Search for Endpoints", notes = "Search for public Endpoint resources associated to the given Organization.")
    @Override
    public Bundle getEndpoints(@ApiParam(hidden=true) @Auth OrganizationPrincipal organization) {
        return this.client
                .search()
                .forResource(Endpoint.class)
                .where(Endpoint.ORGANIZATION.hasId(organization.getOrganization().getId()))
                .returnBundle(Bundle.class)
                .encodedJson()
                .execute();
    }

    @GET
    @Path("/{endpointID}")
    @PathAuthorizer(type = DPCResourceType.Endpoint, pathParam = "endpointID")
    @FHIR
    @Timed
    @ExceptionMetered
    @ApiOperation(value = "Fetch Endpoint resource", notes = "Fetch a specific Endpoint associated to an Organization.")
    @ApiResponses(@ApiResponse(code = 404, message = "Endpoint not found"))
    @Override
    public Endpoint fetchEndpoint(@ApiParam @PathParam("endpointID") @NotNull UUID endpointID) {
        return this.client
                .read()
                .resource(Endpoint.class)
                .withId(new IdType("Organization", endpointID.toString()))
                .encodedJson()
                .execute();
    }

    @PUT
    @Path("/{endpointID}")
    @PathAuthorizer(type = DPCResourceType.Endpoint, pathParam = "endpointID")
    @FHIR
    @Timed
    @ExceptionMetered
    @ApiOperation(value = "Update an Organization's FHIR Server Endpoint", notes = "Update an Endpoint resource")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Endpoint updated"),
            @ApiResponse(code = 404, message = "Endpoint not found"),
            @ApiResponse(code = 422, message = "Endpoint not valid")
    })
    @Override
    public Endpoint updateEndpoint(@ApiParam(value = "Your Organization's FHIR Endpoint ID") @NotNull @PathParam("endpointID") UUID endpointID,
                                   @Valid @Profiled Endpoint endpoint) {
        Endpoint currEndpoint = fetchEndpoint(endpointID);
        if (!endpoint.getManagingOrganization().getReference().equals(currEndpoint.getManagingOrganization().getReference())) {
            throw new WebApplicationException("An Endpoint's Organization cannot be changed", HttpStatus.UNPROCESSABLE_ENTITY_422);
        }

        MethodOutcome outcome = this.client
                .update()
                .resource(endpoint)
                .withId(endpointID.toString())
                .encodedJson()
                .execute();

        return (Endpoint) outcome.getResource();
    }

    @DELETE
    @Path("/{endpointID}")
    @PathAuthorizer(type = DPCResourceType.Endpoint, pathParam = "endpointID")
    @FHIR
    @Timed
    @ExceptionMetered
    @ApiOperation(value = "Delete an Endpoint", notes = "Delete an Endpoint resource")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Endpoint deleted"),
            @ApiResponse(code = 404, message = "Endpoint not found"),
            @ApiResponse(code = 422, message = "Endpoint cannot be deleted")
    })
    @Override
    public Response deleteEndpoint(@NotNull @PathParam("endpointID") UUID endpointID) {
        this.client
                .delete()
                .resourceById("Endpoint", endpointID.toString())
                .execute();

        return Response.ok().build();
    }
}