001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.http.commons.exceptionhandlers;
007
008import org.fcrepo.config.FedoraPropsConfig;
009import org.fcrepo.http.commons.api.rdf.HttpIdentifierConverter;
010import org.fcrepo.http.commons.domain.RDFMediaType;
011import org.fcrepo.http.commons.responses.ConcurrentExceptionResponse;
012import org.fcrepo.kernel.api.exception.ConcurrentUpdateException;
013import org.slf4j.Logger;
014
015import javax.inject.Inject;
016import javax.ws.rs.core.Context;
017import javax.ws.rs.core.Response;
018import javax.ws.rs.core.UriInfo;
019import javax.ws.rs.ext.ExceptionMapper;
020import javax.ws.rs.ext.Provider;
021
022import static javax.ws.rs.core.Response.status;
023import static org.fcrepo.http.commons.session.TransactionConstants.TX_PREFIX;
024import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_ID_PREFIX;
025import static org.slf4j.LoggerFactory.getLogger;
026
027/**
028 * @author pwinckles
029 */
030@Provider
031public class ConcurrentUpdateExceptionMapper implements
032        ExceptionMapper<ConcurrentUpdateException>, ExceptionDebugLogging {
033
034    private static final Logger LOGGER = getLogger(ConcurrentUpdateExceptionMapper.class);
035
036    @Inject
037    private FedoraPropsConfig config;
038
039    @Context
040    private UriInfo uriInfo;
041
042    @Override
043    public Response toResponse(final ConcurrentUpdateException e) {
044        debugException(this, e, LOGGER);
045        final var response = new ConcurrentExceptionResponse(e.getResponseMessage());
046
047        // create external links for the transaction ids
048        if (config.includeTransactionOnConflict()) {
049            final var identifierConverter = new HttpIdentifierConverter(uriInfo.getBaseUriBuilder()
050                                                                               .clone().path("/{path: .*}"));
051            final var existingId = FEDORA_ID_PREFIX + "/" + TX_PREFIX + e.getExistingTransactionId();
052            final var conflictingId = FEDORA_ID_PREFIX + "/" + TX_PREFIX + e.getConflictingTransactionId();
053            response.setExistingTransactionId(identifierConverter.toExternalId(existingId));
054            response.setConflictingTransactionId(identifierConverter.toExternalId(conflictingId));
055        }
056
057        return status(Response.Status.CONFLICT)
058            .entity(response)
059            .type(RDFMediaType.APPLICATION_JSON_TYPE).build();
060    }
061
062}