package com.bj58.argo.internal;
import com.bj58.argo.Argo;
import com.bj58.argo.ArgoController;
import com.bj58.argo.BeatContext;
import com.bj58.argo.inject.ArgoSystem;
import com.bj58.argo.ActionResult;
import com.bj58.argo.logs.Logger;
import com.bj58.argo.route.*;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
import java.util.Set;
@Singleton
public class DefaultRouter implements Router {
private final Argo argo;
private final List<Action> actions;
@Inject
public DefaultRouter(Argo argo, @ArgoSystem Set<Class<? extends ArgoController>> controllerClasses, @StaticActionAnnotation Action staticAction) {
this.argo = argo;
argo.getLogger().info("initializing a %s(implements Router)", this.getClass());
this.actions = buildActions(argo, controllerClasses, staticAction);
argo.getLogger().info("%s(implements Router) constructed.", this.getClass());
}
@Override
public ActionResult route(BeatContext beat) {
RouteBag bag = RouteBag.create(beat);
for(Action action : actions) {
RouteResult routeResult = action.matchAndInvoke(bag);
if (routeResult.isSuccess())
return routeResult.getResult();
}
return ActionResult.NULL;
}
List<Action> buildActions(Argo argo, Set<Class<? extends ArgoController>> controllerClasses, Action staticAction) {
Set<ArgoController> controllers = getControllerInstances(argo, controllerClasses);
return buildActions(controllers, staticAction);
}
private Set<ArgoController> getControllerInstances(final Argo argo, Set<Class<? extends ArgoController>> controllerClasses) {
Iterable<ArgoController> sets = Iterables.transform(controllerClasses, new Function<Class<? extends ArgoController>, ArgoController>() {
@Override
public ArgoController apply(Class<? extends ArgoController> clazz) {
// instance a controller
ArgoController controller = argo.getInstance(clazz);
// initialize the controller.
controller.init();
return controller;
}
});
return ImmutableSet.copyOf(sets);
}
//TODO:static files actions.
List<Action> buildActions(Set<ArgoController> controllers, Action staticAction) {
List<Action> actions = Lists.newArrayList();
actions.add(staticAction);
for (ArgoController controller : controllers) {
ControllerInfo controllerInfo = new ControllerInfo(controller);
List<ActionInfo> subActions = controllerInfo.analyze();
for(ActionInfo newAction : subActions)
merge(actions, MethodAction.create(newAction));
}
return ImmutableList.copyOf(actions);
}
void merge(List<Action> actions, Action newAction) {
for (int index = 0; index < actions.size(); index++) {
Action action = actions.get(index);
if(action.order() > newAction.order()) {
actions.add(index, newAction);
return;
}
}
actions.add(newAction);
}
}