/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.jooby.internal;
import java.util.List;
import java.util.Map;
import org.jooby.Request;
import org.jooby.Response;
import org.jooby.Route;
import com.google.common.collect.ImmutableMap;
public class RouteChain implements Route.Chain {
private List<Route> routes;
private String prefix;
private int i = 0;
private RequestImpl rreq;
private ResponseImpl rrsp;
private boolean hasAttrs;
public RouteChain(final RequestImpl req, final ResponseImpl rsp, final List<Route> routes) {
this.routes = routes;
this.rreq = req;
this.rrsp = rsp;
// eager decision if we need to wrap a route to get all the attrs within the change.
this.hasAttrs = hasAttributes(routes);
}
private boolean hasAttributes(final List<Route> routes) {
for (int i = 0; i < routes.size(); i++) {
if (routes.get(i).attributes().size() > 0) {
return true;
}
}
return false;
}
@Override
public void next(final String prefix, final Request req, final Response rsp) throws Throwable {
if (rsp.committed()) {
return;
}
if (prefix != null) {
this.prefix = prefix;
}
Route route = next(this.prefix);
// set route
rreq.route(hasAttrs ? attrs(route, routes, i - 1) : route);
rrsp.route(route);
get(route).handle(req, rsp, this);
}
private Route next(final String prefix) {
Route route = routes.get(i++);
if (prefix == null) {
return route;
}
while (!route.apply(prefix)) {
route = routes.get(i++);
}
return route;
}
private RouteWithFilter get(final Route next) {
return (RouteWithFilter) Route.Forwarding.unwrap(next);
}
private static Route attrs(final Route route, final List<Route> routes, final int i) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
for (int t = i; t < routes.size(); t++) {
builder.putAll(routes.get(t).attributes());
}
Map<String, Object> attrs = builder.build();
return new Route.Forwarding(route) {
@Override
public Map<String, Object> attributes() {
return attrs;
}
};
}
}