All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wisdom.api.router.RouteUtils Maven / Gradle / Ivy

The newest version!
/*
 * #%L
 * Wisdom-Framework
 * %%
 * Copyright (C) 2013 - 2014 Wisdom Framework
 * %%
 * 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%
 */
package org.wisdom.api.router;

import org.wisdom.api.Controller;
import org.wisdom.api.annotations.Path;
import org.wisdom.api.router.parameters.ActionParameter;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A couple of method easing the manipulation of routes.
 */
public class RouteUtils {
    private static final Pattern PATH_PARAMETER_REGEX = Pattern.compile("\\{(.*?)\\}");
    private static final String ANY_CHARS = "(.*?)";
    public static final String EMPTY_PREFIX = "";


    private RouteUtils() {
        // Avoid direct instantiation, as we only have static methods in this class.
    }

    /**
     * Extracts the name of the parameters from a route.
     * 

* /{my_id}/{my_name} *

* would return a List with "my_id" and "my_name" * * @param rawRoute the route's uri * @return a list with the names of all parameters in that route. */ public static List extractParameters(String rawRoute) { List list = new ArrayList<>(); Matcher m = PATH_PARAMETER_REGEX.matcher(rawRoute); while (m.find()) { if (m.group(1).indexOf('<') != -1) { // Regex case name list.add(m.group(1).substring(0, m.group(1).indexOf('<'))); } else if (m.group(1).indexOf('*') != -1) { // Star case name* list.add(m.group(1).substring(0, m.group(1).indexOf('*'))); } else if (m.group(1).indexOf('+') != -1) { // Plus case name+ list.add(m.group(1).substring(0, m.group(1).indexOf('+'))); } else { // Basic case (name) list.add(m.group(1)); } } return list; } /** * Gets a raw uri like /{name}/id/* and returns /(.*)/id/*. * * @param rawUri the uri * @return The regex */ public static String convertRawUriToRegex(String rawUri) { StringBuilder builder = new StringBuilder(); boolean inRegexp = false; boolean inVariablePlaceholder = false; boolean wasRegexp = false; String current = ""; for (char c : rawUri.toCharArray()) { // First "{" if (!inVariablePlaceholder && c == '{') { inVariablePlaceholder = true; wasRegexp = false; inRegexp = false; current = ""; } // No in a variable placeholder if (!inVariablePlaceholder) { builder.append(c); continue; } // In brace. // Ending "}" if (!inRegexp && c == '}') { inVariablePlaceholder = false; if (wasRegexp) { continue; } if (current.endsWith("*")) { builder.append(ANY_CHARS); } else if (current.endsWith("+")) { builder.append("(.+?)"); } else { builder.append("([^/]+?)"); } continue; } // In regex if (inRegexp && c != '>') { builder.append(c); continue; } // Start a regex if (!inRegexp && c == '<') { inRegexp = true; wasRegexp = true; builder.append("("); continue; } // End of regex if (inRegexp && c == '>') { inRegexp = false; builder.append(")"); continue; } // We are in brace. current += c; } if (inRegexp) { throw new IllegalArgumentException("Invalid route uri - the regex part is not closed: " + rawUri); } if (inVariablePlaceholder) { throw new IllegalArgumentException("Invalid route uri - the variable placeholder is not closed: " + rawUri); } String s = builder.toString(); // Replace ending * by (.*?) if (s.endsWith("*")) { s = s.substring(0, s.length() - 1) + ANY_CHARS; } return s; } /** * Collects the @Route annotation on action method. * This set will be added at the end of the list retrieved from the {@link org.wisdom.api * .Controller#routes()} * * @param controller the controller * @return the list of route, empty if none are available */ public static List collectRouteFromControllerAnnotations(Controller controller) { String prefix = getPath(controller); List routes = new ArrayList<>(); Method[] methods = controller.getClass().getMethods(); for (Method method : methods) { org.wisdom.api.annotations.Route annotation = method.getAnnotation(org.wisdom.api.annotations.Route.class); if (annotation != null) { String uri = annotation.uri(); uri = getPrefixedUri(prefix, uri); final Route route = new RouteBuilder().route(annotation.method()) .on(uri) .to(controller, method) .accepting(annotation.accepts()) .producing(annotation.produces()); routes.add(route); } } return routes; } /** * Prepends the given prefix to the given uri. * * @param prefix the prefix * @param uri the uri * @return the full uri */ public static String getPrefixedUri(String prefix, String uri) { String localURI = uri; if (localURI.length() > 0) { // Put a / between the prefix and the tail only if: // the prefix does not ends with a / // the tail does not start with a / // the tail starts with an alphanumeric character. if (!localURI.startsWith("/") && !prefix.endsWith("/") && Character.isLetterOrDigit(localURI.indexOf(0))) { localURI = prefix + "/" + localURI; } else { localURI = prefix + localURI; } } else { // Empty tail, just return the prefix. return prefix; } return localURI; } /** * Gets the list of Argument, i.e. formal parameter metadata for the given method. * * @param method the method * @return the list of arguments */ public static List buildActionParameterList(Method method) { List arguments = new ArrayList<>(); Annotation[][] annotations = method.getParameterAnnotations(); Class[] typesOfParameters = method.getParameterTypes(); Type[] genericTypeOfParameters = method.getGenericParameterTypes(); for (int i = 0; i < annotations.length; i++) { arguments.add(ActionParameter.from(method, annotations[i], typesOfParameters[i], genericTypeOfParameters[i])); } return arguments; } /** * Gets the 'path' value of the given controller. If the controller does not use the {@link org.wisdom.api * .annotations.Path} annotation, and empty prefix is returned. * * @param controller the controller * @return the prefix coming either empty or the value of the Path annotation */ public static String getPath(Controller controller) { Path path = controller.getClass().getAnnotation(Path.class); if (path == null) { return EMPTY_PREFIX; } else { return path.value(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy