class CatalogRest {

    @GET
    @Path("{catalogId}/records/{recordId}/branches/{branchId}/commits")
    @Produces(MediaType.APPLICATION_JSON)
    @RolesAllowed("user")
    @ApiOperation("Gets the Commit chain for a specific Branch.")
    @ResourceId(type = ValueType.PATH, value = "recordId")
    public Response getCommitChain(@Context UriInfo uriInfo,
                            @PathParam("catalogId") String catalogId,
                            @PathParam("recordId") String recordId,
                            @PathParam("branchId") String branchId,
                            @QueryParam("targetId") String targetId,
                            @QueryParam("offset") int offset,
                            @QueryParam("limit") int limit) {
        LinksUtils.validateParams(limit, offset);

        try {
            ArrayNode commitChain = mapper.createArrayNode();

            final List<Commit> commits;
            if (StringUtils.isBlank(targetId)) {
                commits = catalogManager.getCommitChain(vf.createIRI(catalogId), vf.createIRI(recordId),
                        vf.createIRI(branchId));
            } else {
                commits = catalogManager.getCommitChain(vf.createIRI(catalogId), vf.createIRI(recordId),
                        vf.createIRI(branchId), vf.createIRI(targetId));
            }
            Stream<Commit> result = commits.stream();
            if (limit > 0) {
                result = result.skip(offset)
                        .limit(limit);
            }
            result.map(r -> createCommitJson(r, vf, engineManager)).forEach(commitChain::add);
            return createPaginatedResponseWithJsonNode(uriInfo, commitChain, commits.size(), limit, offset);
        } catch (IllegalArgumentException ex) {
            throw ErrorUtils.sendError(ex, ex.getMessage(), Response.Status.BAD_REQUEST);
        } catch (IllegalStateException | MobiException ex) {
            throw ErrorUtils.sendError(ex, ex.getMessage(), Response.Status.INTERNAL_SERVER_ERROR);
        }
    }

}