package org.ow2.chameleon.wisdom.api.route;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import org.ow2.chameleon.wisdom.api.Controller;
import org.ow2.chameleon.wisdom.api.http.HttpMethod;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Represents a route.
 */
public class Route {

    private final HttpMethod httpMethod;
    private final String uri;
    private final Controller controller;
    private final Method controllerMethod;
    private final List<String> parameterNames;
    private final Pattern regex;

    public Route(HttpMethod httpMethod,
                 String uri,
                 Controller controller,
                 Method controllerMethod) {
        this.httpMethod = httpMethod;
        this.uri = uri;
        this.controller = controller;
        this.controllerMethod = controllerMethod;

        parameterNames = ImmutableList.copyOf(RouteUtils.extractParameters(uri));
        regex = Pattern.compile(RouteUtils.convertRawUriToRegex(uri));
    }

    public String getUrl() {
        return uri;
    }

    public HttpMethod getHttpMethod() {
        return httpMethod;
    }

    public Class<? extends Controller> getControllerClass() {
        return controller.getClass();
    }

    public Method getControllerMethod() {
        return controllerMethod;
    }

    /**
     * Matches /index to /index or /me/1 to /person/{id}
     *
     * @return True if the actual route matches a raw rout. False if not.
     */
    public boolean matches(HttpMethod method, String uri) {
        if (this.httpMethod == method) {
            Matcher matcher = regex.matcher(uri);
            return matcher.matches();
        } else {
            return false;
        }
    }

    /**
     * Matches /index to /index or /me/1 to /person/{id}
     *
     * @return True if the actual route matches a raw rout. False if not.
     */
    public boolean matches(String httpMethod, String uri) {
        return matches(HttpMethod.from(httpMethod), uri);
    }

    /**
     * This method does not do any decoding / encoding.
     * <p/>
     * If you want to decode you have to do it yourself.
     * <p/>
     * Most likely with:
     * http://docs.oracle.com/javase/6/docs/api/java/net/URI.html
     *
     * @param uri The whole encoded uri.
     * @return A map with all parameters of that uri. Encoded in => encoded out.
     */
    public Map<String, String> getPathParametersEncoded(String uri) {

        Map<String, String> map = Maps.newHashMap();

        Matcher m = regex.matcher(uri);

        if (m.matches()) {
            for (int i = 1; i < m.groupCount() + 1; i++) {
                map.put(parameterNames.get(i - 1), m.group(i));
            }
        }

        return map;

    }

    public Controller getControllerObject() {
        return controller;
    }

    @Override
    public String toString() {
        return "{"
                + String.valueOf(getHttpMethod()) + " " + uri + " => "
                + controller.getClass().toString() + "#" + controllerMethod.getName()
                + "}";
    }
}

@@ -3195,11 +3195,755 @@
 %22;%0A    %7D
+%0A%0A    @Override%0A    public boolean equals(Object o) %7B%0A        if (this == o) return true;%0A        if (o == null %7C%7C getClass() != o.getClass()) return false;%0A%0A        Route route = (Route) o;%0A%0A        if (!controller.equals(route.controller)) return false;%0A        if (!controllerMethod.equals(route.controllerMethod)) return false;%0A        if (httpMethod != route.httpMethod) return false;%0A        if (!uri.equals(route.uri)) return false;%0A%0A        return true;%0A    %7D%0A%0A    @Override%0A    public int hashCode() %7B%0A        int result = httpMethod.hashCode();%0A        result = 31 * result + uri.hashCode();%0A        result = 31 * result + controller.hashCode();%0A        result = 31 * result + controllerMethod.hashCode();%0A        return result;%0A    %7D
 %0A%7D%0A

Implement hashCode and equals in route