package restx.apidocs;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.base.CaseFormat;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import restx.*;
import restx.endpoint.Endpoint;
import restx.admin.AdminModule;
import restx.endpoint.EndpointParameterMapperRegistry;
import restx.factory.Component;
import restx.factory.Factory;
import restx.factory.NamedComponent;
import restx.jackson.FrontObjectMapperFactory;
import restx.jackson.StdJsonProducerEntityRoute;
import restx.security.PermissionFactory;
import restx.security.RestxSecurityManager;
import restx.security.PermissionFactory;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Serves the swagger resource listing, which looks like that:
* {
* "apiVersion":"0.2",
* "swaggerVersion":"1.1",
* "basePath":"http://petstore.swagger.wordnik.com/api",
* "apis":[
* {
* "path":"/api-docs.{format}/user",
* "description":""
* },
* {
* "path":"/api-docs.{format}/pet",
* "description":""
* }
* ]
* }
*/
@Component
public class ApiDocsIndexRoute extends StdJsonProducerEntityRoute {
private final Factory factory;
private final RestxSecurityManager securityManager;
@Inject
public ApiDocsIndexRoute(
@Named(FrontObjectMapperFactory.WRITER_NAME) ObjectWriter writer,
Factory factory,
RestxSecurityManager securityManager,
PermissionFactory permissionFactory,
EndpointParameterMapperRegistry registry) {
super("ApiDocsIndexRoute", Map.class, writer, Endpoint.of("GET", "/@/api-docs"), permissionFactory, registry);
this.factory = factory;
this.securityManager = securityManager;
}
@Override
protected Optional<?> doRoute(RestxRequest restxRequest, RestxRequestMatch match, Object i) throws IOException {
securityManager.check(restxRequest, match, hasRole(AdminModule.RESTX_ADMIN_ROLE));
return Optional.of(ImmutableMap.builder()
.put("apiVersion", "0.1") // TODO
.put("swaggerVersion", "1.1")
.put("basePath", restxRequest.getBaseNetworkPath())
.put("apis", buildApis())
.build());
}
private List<ImmutableMap<String, String>> buildApis() {
Set<NamedComponent<RestxRouter>> routers = factory.queryByClass(RestxRouter.class).find();
List<ImmutableMap<String, String>> apis = Lists.newArrayList();
for (NamedComponent<RestxRouter> router : routers) {
String routerApiPath = getRouterApiPath(router.getName().getName());
if (ApiDeclarationRoute.getRouterByName(factory, routerApiPath).isPresent()) {
// we add the api only if we can find back the router from the name, otherwise it will trigger
// 404 errors in API-DOCS
apis.add(ImmutableMap.of(
"path", "/@/api-docs/" + routerApiPath,
"name", routerApiPath,
"group", router.getComponent().getGroupName(),
"description", ""));
}
}
return apis;
}
static String getRouterApiPath(String path) {
path = path.replaceAll("Router$", "").replaceAll("Resource$", "");
path = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, path);
return path;
}
}