package com.sebastian_daschner.jaxrs_analyzer.backend.asciidoc; import com.sebastian_daschner.jaxrs_analyzer.backend.StringBackend; import com.sebastian_daschner.jaxrs_analyzer.model.Types; import com.sebastian_daschner.jaxrs_analyzer.model.rest.*; import com.sebastian_daschner.jaxrs_analyzer.utils.StringUtils; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.mapKeyComparator; import static com.sebastian_daschner.jaxrs_analyzer.backend.ComparatorUtils.parameterComparator; import static com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils.toReadableType; /** * A backend implementation which produces an AsciiDoc representation of the JAX-RS project. * * @author Sebastian Daschner */ public class AsciiDocBackend extends StringBackend { private static final String NAME = "AsciiDoc"; private static final String DOCUMENT_TITLE = "= REST resources of "; private static final String TYPE_WILDCARD = "\\*/*"; @Override protected void appendMethod(final String baseUri, final String resource, final ResourceMethod resourceMethod) { builder.append("== `").append(resourceMethod.getMethod()).append(' '); if (!StringUtils.isBlank(baseUri)) builder.append(baseUri).append('/'); builder.append(resource).append("`\n\n"); if (resourceMethod.isDeprecated()) builder.append("CAUTION: deprecated\n\n"); } @Override protected void appendRequest(final ResourceMethod resourceMethod) { builder.append("=== Request\n"); if (resourceMethod.getRequestBody() != null) { builder.append("*Content-Type*: `"); builder.append(resourceMethod.getRequestMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getRequestMediaTypes())); builder.append("` + \n"); builder.append("*Request Body*: (").append(toTypeOrCollection(resourceMethod.getRequestBody())).append(") + \n"); Optional.ofNullable(resources.getTypeRepresentations().get(resourceMethod.getRequestBody())).ifPresent(r -> { builder.append('`'); r.accept(visitor); builder.append("` + \n"); }); } else { builder.append("_No body_ + \n"); } final Set<MethodParameter> parameters = resourceMethod.getMethodParameters(); appendParams("Path Param", parameters, ParameterType.PATH); appendParams("Query Param", parameters, ParameterType.QUERY); appendParams("Form Param", parameters, ParameterType.FORM); appendParams("Header Param", parameters, ParameterType.HEADER); appendParams("Cookie Param", parameters, ParameterType.COOKIE); appendParams("Matrix Param", parameters, ParameterType.MATRIX); builder.append('\n'); } private void appendParams(final String name, final Set<MethodParameter> parameters, final ParameterType parameterType) { parameters.stream().filter(p -> p.getParameterType() == parameterType) .sorted(parameterComparator()).forEach(p -> builder .append('*') .append(name) .append("*: `") .append(p.getName()) .append("`, `") .append(toReadableType(p.getType().getType())) // TODO add default value .append("` + \n")); } @Override protected void appendResponse(final ResourceMethod resourceMethod) { builder.append("=== Response\n"); builder.append("*Content-Type*: `"); builder.append(resourceMethod.getResponseMediaTypes().isEmpty() ? TYPE_WILDCARD : toString(resourceMethod.getResponseMediaTypes())); builder.append("`\n\n"); resourceMethod.getResponses().entrySet().stream().sorted(mapKeyComparator()).forEach(e -> { builder.append("==== `").append(e.getKey()).append(' ') .append(javax.ws.rs.core.Response.Status.fromStatusCode(e.getKey()).getReasonPhrase()).append("`\n"); final Response response = e.getValue(); response.getHeaders().forEach(h -> builder.append("*Header*: `").append(h).append("` + \n")); if (response.getResponseBody() != null) { builder.append("*Response Body*: ").append('(').append(toTypeOrCollection(response.getResponseBody())).append(") + \n"); Optional.ofNullable(resources.getTypeRepresentations().get(response.getResponseBody())).ifPresent(r -> { builder.append('`'); r.accept(visitor); builder.append("` + \n"); }); } builder.append('\n'); }); } private String toTypeOrCollection(final TypeIdentifier type) { final TypeRepresentation representation = resources.getTypeRepresentations().get(type); if (representation != null && !representation.getComponentType().equals(type) && !type.getType().equals(Types.JSON)) { return "Collection of `" + toReadableType(representation.getComponentType().getType()) + '`'; } return '`' + toReadableType(type.getType()) + '`'; } private static String toString(final Set<String> set) { return set.stream().sorted().map(Object::toString).collect(Collectors.joining(", ")); } @Override public String getName() { return NAME; } @Override protected void appendFirstLine() { builder.append(DOCUMENT_TITLE).append(projectName).append("\n"); } }