@Override
 public boolean isDocumentationRequest(RestRequest request) {
   final String path = request.getURI().getRawPath();
   final List<UriComponent.PathSegment> pathSegments = UriComponent.decodePath(path, true);
   return (pathSegments.size() > 2
           && DOC_PREFIX.equals(pathSegments.get(1).getPath())
           && DOC_VIEW_DOCS_ACTION.equals(pathSegments.get(2).getPath()))
       || HttpMethod.valueOf(request.getMethod()) == HttpMethod.OPTIONS;
 }
  @Override
  @SuppressWarnings("fallthrough")
  public RestResponse processDocumentationRequest(RestRequest request) {
    final String path = request.getURI().getRawPath();
    final List<UriComponent.PathSegment> pathSegments = UriComponent.decodePath(path, true);

    String prefixSegment = null;
    String actionSegment = null;
    String typeSegment = null;
    String objectSegment = null;

    switch (pathSegments.size()) {
      case 5:
        objectSegment = pathSegments.get(4).getPath();
      case 4:
        typeSegment = pathSegments.get(3).getPath();
      case 3:
        actionSegment = pathSegments.get(2).getPath();
      case 2:
        prefixSegment = pathSegments.get(1).getPath();
    }

    assert (prefixSegment.equals(DOC_PREFIX)
        || (HttpMethod.valueOf(request.getMethod()) == HttpMethod.OPTIONS));

    final ByteArrayOutputStream out = new ByteArrayOutputStream(BAOS_BUFFER_SIZE);
    final RestLiDocumentationRenderer renderer;

    if (HttpMethod.valueOf(request.getMethod()) == HttpMethod.OPTIONS) {
      renderer = _jsonRenderer;
      renderer.renderResource(prefixSegment, out);
    } else if (HttpMethod.valueOf(request.getMethod()) == HttpMethod.GET) {
      if (!DOC_VIEW_DOCS_ACTION.equals(actionSegment)) {
        throw createRoutingError(path);
      }

      final MultivaluedMap queryMap = UriComponent.decodeQuery(request.getURI().getQuery(), false);
      final List<String> formatList = queryMap.get("format");
      if (formatList == null) {
        renderer = _htmlRenderer;
      } else if (formatList.size() > 1) {
        throw new RoutingException(
            String.format(
                "\"format\" query parameter must be unique, where multiple are specified: %s",
                Arrays.toString(formatList.toArray())),
            HttpStatus.S_400_BAD_REQUEST.getCode());
      } else {
        renderer = (formatList.contains(DOC_JSON_FORMAT) ? _jsonRenderer : _htmlRenderer);
      }

      if (renderer == _htmlRenderer) {
        _htmlRenderer.setJsonFormatUri(
            UriBuilder.fromUri(request.getURI()).queryParam("format", DOC_JSON_FORMAT).build());
      }

      try {
        if (typeSegment == null || typeSegment.isEmpty()) {
          renderer.renderHome(out);
        } else {
          if (DOC_RESOURCE_TYPE.equals(typeSegment)) {
            if (objectSegment == null || objectSegment.isEmpty()) {
              renderer.renderResourceHome(out);
            } else {
              renderer.renderResource(objectSegment, out);
            }
          } else if (DOC_DATA_TYPE.equals(typeSegment)) {
            if (objectSegment == null || objectSegment.isEmpty()) {
              renderer.renderDataModelHome(out);
            } else {
              renderer.renderDataModel(objectSegment, out);
            }
          } else {
            throw createRoutingError(path);
          }
        }
      } catch (RuntimeException e) {
        if (!renderer.handleException(e, out)) {
          throw e;
        }
      }
    } else {
      throw new RoutingException(HttpStatus.S_405_METHOD_NOT_ALLOWED.getCode());
    }

    return new RestResponseBuilder()
        .setStatus(HttpStatus.S_200_OK.getCode())
        .setHeader(RestConstants.HEADER_CONTENT_TYPE, renderer.getMIMEType())
        .setEntity(out.toByteArray())
        .build();
  }