Search in sources :

Example 1 with ResourceVersionConflictException

use of ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException in project gpconnect-demonstrator by nhsconnect.

the class AppointmentResourceProvider method updateAppointment.

@Update
public MethodOutcome updateAppointment(@IdParam IdType appointmentId, @ResourceParam Appointment appointment) {
    MethodOutcome methodOutcome = new MethodOutcome();
    OperationOutcome operationalOutcome = new OperationOutcome();
    AppointmentDetail appointmentDetail = appointmentResourceConverterToAppointmentDetail(appointment);
    // URL ID and Resource ID must be the same
    if (!Objects.equals(appointmentId.getIdPartAsLong(), appointmentDetail.getId())) {
        operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("Id in URL (" + appointmentId.getIdPart() + ") should match Id in Resource (" + appointmentDetail.getId() + ")");
        methodOutcome.setOperationOutcome(operationalOutcome);
        return methodOutcome;
    }
    // Make sure there is an existing appointment to be amended
    AppointmentDetail oldAppointmentDetail = appointmentSearch.findAppointmentByID(appointmentId.getIdPartAsLong());
    if (oldAppointmentDetail == null) {
        operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("No appointment details found for ID: " + appointmentId.getIdPart());
        methodOutcome.setOperationOutcome(operationalOutcome);
        return methodOutcome;
    }
    String oldAppointmentVersionId = String.valueOf(oldAppointmentDetail.getLastUpdated().getTime());
    String newAppointmentVersionId = appointmentId.getVersionIdPart();
    if (newAppointmentVersionId != null && !newAppointmentVersionId.equalsIgnoreCase(oldAppointmentVersionId)) {
        throw new ResourceVersionConflictException("The specified version (" + newAppointmentVersionId + ") did not match the current resource version (" + oldAppointmentVersionId + ")");
    }
    // Determin if it is a cancel or an amend
    if (appointmentDetail.getCancellationReason() != null) {
        if (appointmentDetail.getCancellationReason().isEmpty()) {
            operationalOutcome.addIssue().setSeverity(IssueSeverity.ERROR).setDiagnostics("The cancellation reason can not be blank");
            methodOutcome.setOperationOutcome(operationalOutcome);
            return methodOutcome;
        }
        // This is a Cancellation - so copy across fields which can be
        // altered
        boolean cancelComparisonResult = compareAppointmentsForInvalidPropertyCancel(oldAppointmentDetail, appointmentDetail);
        if (cancelComparisonResult) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(400, "Invalid Appointment property has been amended (cancellation)"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        oldAppointmentDetail.setCancellationReason(appointmentDetail.getCancellationReason());
        String oldStatus = oldAppointmentDetail.getStatus();
        appointmentDetail = oldAppointmentDetail;
        appointmentDetail.setStatus("cancelled");
        if (!"cancelled".equalsIgnoreCase(oldStatus)) {
            for (Long slotId : appointmentDetail.getSlotIds()) {
                SlotDetail slotDetail = slotSearch.findSlotByID(slotId);
                // slotDetail.setAppointmentId(null);
                slotDetail.setFreeBusyType("FREE");
                slotDetail.setLastUpdated(new Date());
                slotStore.saveSlot(slotDetail);
            }
        }
    } else {
        if (appointment.getStatus().equals("cancelled")) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(400, "Appointment has been cancelled and cannot be amended"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        boolean amendComparisonResult = compareAppointmentsForInvalidPropertyAmend(appointmentDetail, oldAppointmentDetail);
        if (amendComparisonResult) {
            throw OperationOutcomeFactory.buildOperationOutcomeException(new UnclassifiedServerFailureException(403, "Invalid Appointment property has been amended"), SystemCode.BAD_REQUEST, IssueType.FORBIDDEN);
        }
        // This is an Amend
        oldAppointmentDetail.setComment(appointmentDetail.getComment());
        oldAppointmentDetail.setReasonCode(appointmentDetail.getReasonCode());
        oldAppointmentDetail.setDescription(appointmentDetail.getDescription());
        oldAppointmentDetail.setReasonDisplay(appointmentDetail.getReasonDisplay());
        oldAppointmentDetail.setTypeCode(appointmentDetail.getTypeCode());
        oldAppointmentDetail.setTypeDisplay(appointmentDetail.getTypeDisplay());
        appointmentDetail = oldAppointmentDetail;
    }
    List<SlotDetail> slots = new ArrayList<>();
    for (Long slotId : appointmentDetail.getSlotIds()) {
        SlotDetail slotDetail = slotSearch.findSlotByID(slotId);
        if (slotDetail == null) {
            throw new UnprocessableEntityException("Slot resource reference is not a valid resource");
        }
        slots.add(slotDetail);
    }
    // Update version and
    appointmentDetail.setLastUpdated(new Date());
    // lastUpdated timestamp
    appointmentDetail = appointmentStore.saveAppointment(appointmentDetail, slots);
    methodOutcome.setId(new IdDt("Appointment", appointmentDetail.getId()));
    methodOutcome.setResource(appointmentDetailToAppointmentResourceConverter(appointmentDetail));
    return methodOutcome;
}
Also used : UnprocessableEntityException(ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException) AppointmentDetail(uk.gov.hscic.model.appointment.AppointmentDetail) ArrayList(java.util.ArrayList) IdDt(ca.uhn.fhir.model.primitive.IdDt) ResourceVersionConflictException(ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException) MethodOutcome(ca.uhn.fhir.rest.api.MethodOutcome) Date(java.util.Date) UnclassifiedServerFailureException(ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException) OperationOutcome(org.hl7.fhir.dstu3.model.OperationOutcome) SlotDetail(uk.gov.hscic.model.appointment.SlotDetail) Update(ca.uhn.fhir.rest.annotation.Update)

Example 2 with ResourceVersionConflictException

use of ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException in project gpconnect-demonstrator by nhsconnect.

the class FhirRequestGenericIntercepter method preProcessOutgoingException.

/**
 * Listens for any exceptions thrown. In the case of invalid parameters, we
 * need to catch this and throw it as a UnprocessableEntityException.
 *
 * @param theRequestDetails
 * @param theException
 * @param theServletRequest
 * @return UnprocessableEntityException if a InvalidRequestException was
 * thrown.
 * @throws javax.servlet.ServletException
 */
@Override
public BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException {
    LOG.info("Response Exception");
    LOG.info(theException.getMessage());
    LOG.info("stackTrace: ", theException);
    // how else to pick up on just the relevant exceptions!
    if (theException instanceof InvalidRequestException && theException.getMessage().contains("Invalid attribute value")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException(theException.getMessage()), SystemCode.INVALID_PARAMETER, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().contains("Unknown resource in URI")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new ResourceNotFoundException(theException.getMessage()), SystemCode.BAD_REQUEST, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().contains("Can not have multiple date range parameters for the same param ")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException(theException.getMessage()), SystemCode.INVALID_PARAMETER, IssueType.INVALID);
    }
    if (theException instanceof DataFormatException) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException(theException.getMessage()), SystemCode.INVALID_PARAMETER, IssueType.INVALID);
    }
    if (theException instanceof MethodNotAllowedException && theException.getMessage().contains("request must use HTTP GET")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException(theException.getMessage()), SystemCode.BAD_REQUEST, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().startsWith("Failed to parse request body as JSON resource. Error was: ")) {
        // #250 422 INVALID_RESOURCE not 400 BAD_REQUEST
        return OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException(theException.getMessage()), SystemCode.INVALID_RESOURCE, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().startsWith("Invalid request: ")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(theException.getMessage()), SystemCode.BAD_REQUEST, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().contains("non-repeatable parameter")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(theException.getMessage()), SystemCode.BAD_REQUEST, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().contains("header blank")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(theException.getMessage()), SystemCode.BAD_REQUEST, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().contains("InvalidResourceType")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException(theException.getMessage()), SystemCode.INVALID_RESOURCE, IssueType.INVALID);
    }
    if (theException instanceof InvalidRequestException && theException.getMessage().contains("Can not create resource with ID")) {
        return OperationOutcomeFactory.buildOperationOutcomeException(new UnprocessableEntityException(theException.getMessage()), SystemCode.BAD_REQUEST, IssueType.INVALID);
    }
    if (theException instanceof ResourceNotFoundException && theException.getMessage().contains("Unknown resource type")) {
        return OperationOutcomeFactory.buildOperationOutcomeException((ResourceNotFoundException) theException, SystemCode.BAD_REQUEST, IssueType.INVALID);
    }
    // }
    if (theException instanceof ResourceVersionConflictException && theException.getMessage().contains("Slot is already in use.")) {
        ResourceVersionConflictException exception = (ResourceVersionConflictException) theException;
        return OperationOutcomeFactory.buildOperationOutcomeException(exception, SystemCode.DUPLICATE_REJECTED, IssueType.CONFLICT);
    }
    if (theException instanceof ResourceVersionConflictException) {
        ResourceVersionConflictException exception = (ResourceVersionConflictException) theException;
        return OperationOutcomeFactory.buildOperationOutcomeException(exception, SystemCode.FHIR_CONSTRAINT_VIOLATION, IssueType.CONFLICT);
    }
    if (theException instanceof BaseServerResponseException) {
        BaseServerResponseException baseServerResponseException = (BaseServerResponseException) theException;
        // If the OperationalOutcome is already set, just return it.
        return null == baseServerResponseException.getOperationOutcome() ? OperationOutcomeFactory.buildOperationOutcomeException(baseServerResponseException, SystemCode.BAD_REQUEST, IssueType.INVALID) : baseServerResponseException;
    }
    // Default catch all.
    return OperationOutcomeFactory.buildOperationOutcomeException(new InvalidRequestException(theException.getMessage()), SystemCode.BAD_REQUEST, IssueType.INVALID);
}
Also used : UnprocessableEntityException(ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException) DataFormatException(ca.uhn.fhir.parser.DataFormatException) MethodNotAllowedException(ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException) InvalidRequestException(ca.uhn.fhir.rest.server.exceptions.InvalidRequestException) ResourceNotFoundException(ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException) ResourceVersionConflictException(ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException) BaseServerResponseException(ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException)

Aggregations

ResourceVersionConflictException (ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException)2 UnprocessableEntityException (ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException)2 IdDt (ca.uhn.fhir.model.primitive.IdDt)1 DataFormatException (ca.uhn.fhir.parser.DataFormatException)1 Update (ca.uhn.fhir.rest.annotation.Update)1 MethodOutcome (ca.uhn.fhir.rest.api.MethodOutcome)1 BaseServerResponseException (ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException)1 InvalidRequestException (ca.uhn.fhir.rest.server.exceptions.InvalidRequestException)1 MethodNotAllowedException (ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException)1 ResourceNotFoundException (ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException)1 UnclassifiedServerFailureException (ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 OperationOutcome (org.hl7.fhir.dstu3.model.OperationOutcome)1 AppointmentDetail (uk.gov.hscic.model.appointment.AppointmentDetail)1 SlotDetail (uk.gov.hscic.model.appointment.SlotDetail)1