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 static org.fcrepo.http.commons.domain.RDFMediaType.TEXT_PLAIN_WITH_CHARSET;
009import static org.slf4j.LoggerFactory.getLogger;
010
011import static javax.ws.rs.core.Response.Status.CONFLICT;
012import static javax.ws.rs.core.Response.status;
013
014import javax.servlet.ServletContext;
015import javax.ws.rs.core.Context;
016import javax.ws.rs.core.Link;
017import javax.ws.rs.core.Response;
018import javax.ws.rs.core.UriInfo;
019import javax.ws.rs.ext.Provider;
020
021import org.fcrepo.kernel.api.exception.ConstraintViolationException;
022import org.fcrepo.kernel.api.exception.MultipleConstraintViolationException;
023import org.fcrepo.kernel.api.exception.RelaxableServerManagedPropertyException;
024import org.fcrepo.kernel.api.exception.ServerManagedPropertyException;
025
026import org.slf4j.Logger;
027
028/**
029 * Mapper to display all the various constrainedby links and messages.
030 * @author whikloj
031 */
032@Provider
033public class MultipleConstraintViolationExceptionMapper extends
034        ConstraintExceptionMapper<MultipleConstraintViolationException> implements ExceptionDebugLogging {
035
036    private static final Logger LOGGER = getLogger(MultipleConstraintViolationExceptionMapper.class);
037
038    @Context
039    private UriInfo uriInfo;
040
041    @Context
042    private ServletContext context;
043
044    @Override
045    public Response toResponse(final MultipleConstraintViolationException e) {
046        debugException(this, e, LOGGER);
047
048        final String msg = e.getMessage();
049        final Response.ResponseBuilder response = status(CONFLICT).entity(msg).type(TEXT_PLAIN_WITH_CHARSET);
050        final Link[] constraintLinks = e.getExceptionTypes().stream().map(ConstraintViolationException::getClass)
051                .distinct().map(c -> {
052                    // Avoid building a link with the relaxable sub-class which would require another constraint RDF
053                    // file.
054                    if (c.equals(RelaxableServerManagedPropertyException.class)) {
055                        return ServerManagedPropertyException.class;
056                    }
057                    return c;
058                }).map(c -> buildConstraintLink(c,
059                        context,
060                        uriInfo))
061                .toArray(Link[]::new);
062        return response.links(constraintLinks).build();
063    }
064
065}