package org.rapidoid.goodies;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.gui.GUI;
import org.rapidoid.html.Tag;
import org.rapidoid.html.tag.TableTag;
import org.rapidoid.http.HttpVerb;
import org.rapidoid.http.Route;
import org.rapidoid.http.RouteConfig;
import org.rapidoid.setup.Admin;
import org.rapidoid.setup.On;
import org.rapidoid.u.U;
import java.util.*;
import java.util.concurrent.Callable;
/*
* #%L
* rapidoid-web
* %%
* Copyright (C) 2014 - 2017 Nikolche Mihajlovski and contributors
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
@Authors("Nikolche Mihajlovski")
@Since("5.1.0")
public class RoutesHandler extends GUI implements Callable<Object> {
@Override
public Object call() throws Exception {
List<Object> routes = U.list();
Set<Route> appRoutes = On.setup().routes().allNonAdmin();
Set<Route> adminRoutes = On.setup().routes().allAdmin();
adminRoutes.addAll(Admin.setup().routes().allAdmin());
routes.add(div(h3("Application routes:"), routesOf(appRoutes, true)));
routes.add(div(h3("Admin routes:"), routesOf(adminRoutes, true)));
return multi(routes);
}
public static TableTag routesOf(Set<Route> httpRoutes, boolean withHandler) {
List<Route> routes = U.list(httpRoutes);
sortRoutes(routes);
List<Object> rows = U.list();
rows.add(tr(th("Verb"), th("Path"), th("Zone"), th("Content type"), th("MVC"), th("View name"), th("Roles"), withHandler ? th("Handler") : null));
while (!routes.isEmpty()) {
Route route = U.first(routes);
List<HttpVerb> verbs = U.list(route.verb());
Iterator<Route> it = routes.iterator();
while (it.hasNext()) {
Route other = it.next();
if (route == other) {
it.remove();
} else if (sameTarget(route, other)) {
verbs.add(other.verb());
it.remove();
}
}
rows.add(routeRow(route, verbs, withHandler));
}
return table_(rows);
}
private static boolean sameTarget(Route a, Route b) {
return !a.verb().equals(b.verb())
&& a.path().equals(b.path())
&& a.handler() == b.handler()
&& a.config().equals(b.config());
}
private static void sortRoutes(List<Route> routes) {
Collections.sort(routes, new Comparator<Route>() {
@Override
public int compare(Route a, Route b) {
int cmpByPath = a.path().compareTo(b.path());
return cmpByPath != 0 ? cmpByPath : a.verb().compareTo(b.verb());
}
});
}
private static Tag routeRow(Route route, List<HttpVerb> verbs, boolean withHandler) {
RouteConfig config = route.config();
Tag verb = td();
for (HttpVerb vrb : verbs) {
verb = verb.append(verb(vrb));
}
Tag path = td(route.path());
Tag zone = td(config.zone());
Tag roles = td(display(config.roles().isEmpty() ? "" : config.roles()));
Tag hnd = td(route.handler());
Tag ctype = td(config.contentType().info());
String viewName = config.mvc() ? viewName(route, config) : "";
Tag view = td(viewName);
Tag mvc = td(config.mvc() ? fa("check") : "");
return tr(verb, path, zone, ctype, mvc, view, roles, withHandler ? hnd : null);
}
private static String viewName(Route route, RouteConfig config) {
return config.view() != null ? config.view() : route.path().substring(1) + " (AUTO)";
}
}