示例#1
0
  final <R extends Route> R add(R route) throws MalformedRouteException {
    if (route == null) {
      throw new NullPointerException("No null route accepted");
    }
    if (((Route) route).parent != null) {
      throw new IllegalArgumentException("No route with an existing parent can be accepted");
    }

    //
    LinkedList<Param> ancestorParams = new LinkedList<Param>();
    findAncestorOrSelfParams(ancestorParams);
    LinkedList<Param> descendantParams = new LinkedList<Param>();
    for (Param param : ancestorParams) {
      ((Route) route).findDescendantOrSelfParams(param.name, descendantParams);
      if (descendantParams.size() > 0) {
        throw new MalformedRouteException("Duplicate parameter " + param.name);
      }
    }

    //
    if (route instanceof PatternRoute || route instanceof SegmentRoute) {
      children = Tools.appendTo(children, route);
      terminal = false;
      ((Route) route).parent = this;
    } else {
      throw new IllegalArgumentException("Only accept segment or pattern routes");
    }

    //
    return route;
  }
示例#2
0
 private Param findParam(QualifiedName name) {
   Param param = getParam(name);
   if (param == null && parent != null) {
     param = parent.findParam(name);
   }
   return param;
 }
示例#3
0
  final Route append(RouteDescriptor descriptor) throws MalformedRouteException {
    Route route = append(descriptor.getPathParams(), descriptor.getPath());

    //
    for (RouteParamDescriptor routeParamDesc : descriptor.getRouteParams()) {
      route.add(RouteParam.create(routeParamDesc));
    }

    //
    for (RequestParamDescriptor requestParamDesc : descriptor.getRequestParams()) {
      route.add(RequestParam.create(requestParamDesc, router));
    }

    //
    for (RouteDescriptor childDescriptor : descriptor.getChildren()) {
      route.append(childDescriptor);
    }

    //
    return route;
  }
示例#4
0
  /**
   * Append a path, creates the necessary routes and returns the last route added.
   *
   * @param pathParamDescriptors the path param descriptors
   * @param path the path to append
   * @return the last route added
   */
  private Route append(Map<QualifiedName, PathParamDescriptor> pathParamDescriptors, String path)
      throws MalformedRouteException {
    if (path.length() == 0 || path.charAt(0) != '/') {
      throw new MalformedRouteException();
    }

    //
    int pos = path.length();
    int level = 0;
    List<Integer> start = new ArrayList<Integer>();
    List<Integer> end = new ArrayList<Integer>();
    for (int i = 1; i < path.length(); i++) {
      char c = path.charAt(i);
      if (c == '{') {
        if (level++ == 0) {
          start.add(i);
        }
      } else if (c == '}') {
        if (--level == 0) {
          end.add(i);
        }
      } else if (c == '/') {
        if (level == 0) {
          pos = i;
          break;
        }
      }
    }

    //
    Route next;
    if (start.isEmpty()) {
      String segment = path.substring(1, pos);
      SegmentRoute route = new SegmentRoute(router, segment);
      add(route);
      next = route;
    } else {
      if (start.size() == end.size()) {
        PatternBuilder builder = new PatternBuilder();
        builder.expr("^").expr('/');
        List<String> chunks = new ArrayList<String>();
        List<PathParam> parameterPatterns = new ArrayList<PathParam>();

        //
        int previous = 1;
        for (int i = 0; i < start.size(); i++) {
          builder.litteral(path, previous, start.get(i));
          chunks.add(path.substring(previous, start.get(i)));
          String parameterName = path.substring(start.get(i) + 1, end.get(i));

          //
          QualifiedName parameterQName = QualifiedName.parse(parameterName);

          // Now get path param metadata
          PathParamDescriptor parameterDescriptor = pathParamDescriptors.get(parameterQName);

          //
          PathParam param;
          if (parameterDescriptor != null) {
            param = PathParam.create(parameterDescriptor, router);
          } else {
            param = PathParam.create(parameterQName, router);
          }

          // Append routing regex to the route regex surrounded by a non capturing regex
          // to isolate routingRegex like a|b or a(.)b
          builder.expr("(?:").expr(param.routingRegex).expr(")");

          // Add the path param with the rendering regex
          parameterPatterns.add(param);
          previous = end.get(i) + 1;
        }

        //
        builder.litteral(path, previous, pos);

        // We want to satisfy one of the following conditions
        // - the next char after the matched expression is '/'
        // - the expression matched until the end
        // - the match expression is the '/' expression
        builder.expr("(?:(?<=^/)|(?=/)|$)");

        //
        chunks.add(path.substring(previous, pos));
        PatternRoute route =
            new PatternRoute(router, router.compile(builder.build()), parameterPatterns, chunks);

        // Wire
        add(route);

        //
        next = route;
      } else {
        throw new UnsupportedOperationException("Report error");
      }
    }

    //
    if (pos < path.length()) {
      return next.append(pathParamDescriptors, path.substring(pos));
    } else {
      return next;
    }
  }
示例#5
0
  private RouteMatch _find(RenderContext context) {
    // Match first the static parameteters
    for (RouteParam param : routeParamArray) {
      RenderContext.Parameter entry = context.getParameter(param.name);
      if (entry != null && !entry.isMatched() && param.value.equals(entry.getValue())) {
        entry.remove(entry.getValue());
      } else {
        return null;
      }
    }

    // Match any request parameter
    for (RequestParam requestParamDef : requestParamArray) {
      RenderContext.Parameter entry = context.getParameter(requestParamDef.name);
      boolean matched = false;
      if (entry != null && !entry.isMatched()) {
        if (requestParamDef.matchPattern == null
            || context.matcher(requestParamDef.matchPattern).matches(entry.getValue())) {
          matched = true;
        }
      }
      if (matched) {
        entry.remove(entry.getValue());
      } else {
        switch (requestParamDef.controlMode) {
          case OPTIONAL:
            // Do nothing
            break;
          case REQUIRED:
            return null;
          default:
            throw new AssertionError();
        }
      }
    }

    // Match any pattern parameter
    if (this instanceof PatternRoute) {
      PatternRoute prt = (PatternRoute) this;
      for (int i = 0; i < prt.params.length; i++) {
        PathParam param = prt.params[i];
        RenderContext.Parameter s = context.getParameter(param.name);
        String matched = null;
        if (s != null && !s.isMatched()) {
          switch (param.encodingMode) {
            case FORM:
            case PRESERVE_PATH:
              for (int j = 0; j < param.matchingRegex.length; j++) {
                Regex renderingRegex = param.matchingRegex[j];
                if (context.matcher(renderingRegex).matches(s.getValue())) {
                  matched = param.templatePrefixes[j] + s.getValue() + param.templateSuffixes[j];
                  break;
                }
              }
              break;
            default:
              throw new AssertionError();
          }
        }
        if (matched != null) {
          s.remove(matched);
        } else {
          return null;
        }
      }
    }

    //
    if (context.isEmpty() && terminal) {
      Map<QualifiedName, String> matches = Collections.emptyMap();
      for (QualifiedName name : context.getNames()) {
        RenderContext.Parameter parameter = context.getParameter(name);
        if (matches.isEmpty()) {
          matches = new HashMap<QualifiedName, String>();
        }
        String match = parameter.getMatch();
        matches.put(name, match);
      }
      return new RouteMatch(context, this, matches);
    }

    //
    for (Route route : children) {
      RouteMatch a = route.find(context);
      if (a != null) {
        return a;
      }
    }

    //
    return null;
  }
示例#6
0
 private void findAncestorOrSelfParams(List<Param> params) {
   findParams(params);
   if (parent != null) {
     parent.findAncestorOrSelfParams(params);
   }
 }