@Test
  public void testMatrixParameters() {
    String segment = "segment";
    String segmentMatrixParam = segment + ";param=value";

    String segmentValue = AbstractURLSegment.getActualSegment(segment);
    assertEquals(segment, segmentValue);

    Map<String, String> matrixParams = AbstractURLSegment.getSegmentMatrixParameters(segment);
    assertTrue(matrixParams.size() == 0);

    segmentValue = AbstractURLSegment.getActualSegment(segmentMatrixParam);
    assertEquals(segment, segmentValue);

    matrixParams = AbstractURLSegment.getSegmentMatrixParameters(segmentMatrixParam);

    assertEquals(1, matrixParams.size());

    assertNotNull(matrixParams.get("param"));

    String segmentMatrixParamsQuotes = segment + ";param=value;param1='hello world'";
    matrixParams = AbstractURLSegment.getSegmentMatrixParameters(segmentMatrixParamsQuotes);

    assertEquals(2, matrixParams.size());
    assertEquals("value", matrixParams.get("param"));
    assertEquals("'hello world'", matrixParams.get("param1"));
  }
  @Test
  public void testParamSegment() throws Exception {
    String segmentWithRegEx = "{id:[0-9]*:abba}";
    AbstractURLSegment segment = AbstractURLSegment.newSegment(segmentWithRegEx);

    assertTrue(segment instanceof ParamSegment);

    ParamSegment paramSegment = (ParamSegment) segment;

    assertEquals(paramSegment.getParamName(), "id");
    assertEquals(paramSegment.getMetaPattern().toString(), "[0-9]*:abba");

    MetaPattern metaPattern = paramSegment.getMetaPattern();

    assertTrue(metaPattern.matcher("1:abba").matches());
    assertTrue(metaPattern.matcher("1234521:abba").matches());
    assertTrue(metaPattern.matcher(":abba").matches());

    String segmentMultiParam =
        "{segment0}asegment{segment1:^\\(?\\d{3}\\)?[ -]?\\d{3}[ -]?\\d{4}$}anotherseg";
    segment = AbstractURLSegment.newSegment(segmentMultiParam);

    assertTrue(segment instanceof MultiParamSegment);

    MultiParamSegment multiParamSegment = (MultiParamSegment) segment;
    List<AbstractURLSegment> subSegments = multiParamSegment.getSubSegments();

    assertEquals(4, subSegments.size());
    metaPattern = subSegments.get(2).getMetaPattern();
    assertEquals(metaPattern.toString(), "^\\(?\\d{3}\\)?[ -]?\\d{3}[ -]?\\d{4}$");

    segmentMultiParam =
        "filename-{symbolicName:[a-z]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}";
    segment = AbstractURLSegment.newSegment(segmentMultiParam);
    multiParamSegment = (MultiParamSegment) segment;
    metaPattern = multiParamSegment.getMetaPatternWithGroups();

    String fileName = "filename-gsaon-1.2.3.zip";
    Matcher matcher = metaPattern.matcher(fileName);

    assertTrue(matcher.matches());

    // testing segment parsing with regular expressions
    assertEquals("gsaon", matcher.group(1));
    assertEquals("1.2.3", matcher.group(2));
    assertEquals(".zip", matcher.group(3));

    matcher = metaPattern.matcher("gsaon-1.2.3.zip");

    assertFalse(matcher.matches());
  }
  /**
   * Method invoked to select the most suited method to serve the current request.
   *
   * @param mappedMethods List of {@link MethodMappingInfo} containing the informations of mapped
   *     methods.
   * @param pageParameters The PageParameters of the current request.
   * @return The "best" method found to serve the request.
   */
  private MethodMappingInfo selectMostSuitedMethod(
      List<MethodMappingInfo> mappedMethods, PageParameters pageParameters) {
    int highestScore = 0;
    MultiMap<Integer, MethodMappingInfo> mappedMethodByScore =
        new MultiMap<Integer, MethodMappingInfo>();

    // no method mapped
    if (mappedMethods == null || mappedMethods.size() == 0) return null;

    /**
     * To select the "best" method, a score is assigned to every mapped method. To calculate the
     * score method calculateScore is executed for every segment.
     */
    for (MethodMappingInfo mappedMethod : mappedMethods) {
      List<AbstractURLSegment> segments = mappedMethod.getSegments();
      int score = 0;

      for (AbstractURLSegment segment : segments) {
        int i = segments.indexOf(segment);
        String currentActualSegment =
            AbstractURLSegment.getActualSegment(pageParameters.get(i).toString());

        int partialScore = segment.calculateScore(currentActualSegment);

        if (partialScore == 0) {
          score = -1;
          break;
        }

        score += partialScore;
      }

      if (score >= highestScore) {
        highestScore = score;
        mappedMethodByScore.addValue(score, mappedMethod);
      }
    }
    // if we have more than one method with the highest score, throw
    // ambiguous exception.
    if (mappedMethodByScore.get(highestScore) != null
        && mappedMethodByScore.get(highestScore).size() > 1)
      throwAmbiguousMethodsException(mappedMethodByScore.get(highestScore));

    return mappedMethodByScore.getFirstValue(highestScore);
  }
  /**
   * Extract method parameter value from matrix parameters.
   *
   * @param pageParameters PageParameters for the current request.
   * @param matrixParam the {@link MatrixParam} annotation used for the current parameter.
   * @param argClass the type of the current method parameter.
   * @return the value obtained from query parameters and converted to argClass.
   */
  private Object extractParameterFromMatrixParams(
      PageParameters pageParameters, MatrixParam matrixParam, Class<?> argClass) {
    int segmentIndex = matrixParam.segmentIndex();
    String variableName = matrixParam.parameterName();
    String rawsSegment = pageParameters.get(segmentIndex).toString();
    Map<String, String> matrixParameters =
        AbstractURLSegment.getSegmentMatrixParameters(rawsSegment);

    if (matrixParameters.get(variableName) == null) return null;

    return toObject(argClass, matrixParameters.get(variableName));
  }