/**
   * Test that a component has been added to a AjaxRequestTarget, using {@link
   * AjaxRequestTarget#addComponent(Component)}. This method actually tests that a component is on
   * the AJAX response sent back to the client.
   *
   * <p>PLEASE NOTE! This method doesn't actually insert the component in the client DOM tree, using
   * javascript. But it shouldn't be needed because you have to trust that the Wicket Ajax
   * Javascript just works.
   *
   * @param component The component to test whether it's on the response.
   */
  public void assertComponentOnAjaxResponse(Component component) {
    String failMessage = "A component which is null could not have been added to the AJAX response";
    Assert.assertNotNull(failMessage, component);

    // Get the AJAX response
    String ajaxResponse = getServletResponse().getDocument();

    // Test that the previous response was actually a AJAX response
    failMessage =
        "The Previous response was not an AJAX response. "
            + "You need to execute an AJAX event, using clickLink, before using this assert";
    boolean isAjaxResponse =
        ajaxResponse.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?><ajax-response>");
    Assert.assertTrue(failMessage, isAjaxResponse);

    // See if the component has a markup id
    String markupId = component.getMarkupId();

    failMessage =
        "The component doesn't have a markup id, "
            + "which means that it can't have been added to the AJAX response";
    Assert.assertFalse(failMessage, Strings.isEmpty(markupId));

    // Look for that the component is on the response, using the markup id
    boolean isComponentInAjaxResponse =
        ajaxResponse.matches(".*<component id=\"" + markupId + "\" ?>.*");
    failMessage = "Component wasn't found in the AJAX response";
    Assert.assertTrue(failMessage, isComponentInAjaxResponse);
  }
  /**
   * Adds page related parameters (path and pagemap and optionally version and interface).
   *
   * <p>If you override this method to behave different then also {@link #encode(RequestCycle,
   * IListenerInterfaceRequestTarget)} should be overridden to by in sync with that behaviour.
   *
   * @param request the incoming request
   * @param parameters the parameters object to set the found values on
   */
  protected void addInterfaceParameters(final Request request, final RequestParameters parameters) {
    // Format of interface target parameter is
    // <page-map-name>:<path>:<version>:<interface>
    final String requestString = request.getParameter(INTERFACE_PARAMETER_NAME);
    if (requestString != null) {
      // Split into array of strings
      String[] pathComponents = Strings.split(requestString, Component.PATH_SEPARATOR);

      // There must be at least 4 components
      if (pathComponents.length < 4) {
        throw new WicketRuntimeException(
            "Internal error parsing " + INTERFACE_PARAMETER_NAME + " = " + requestString);
      }

      // Set pagemap name
      final String pageMapName = pathComponents[0];
      parameters.setPageMapName(pageMapName.length() == 0 ? PageMap.DEFAULT_NAME : pageMapName);

      // Extract interface name after last colon
      final String interfaceName = pathComponents[pathComponents.length - 1];
      parameters.setInterfaceName(
          interfaceName.length() != 0 ? interfaceName : IRedirectListener.INTERFACE.getName());

      // Extract version
      final String versionNumberString = pathComponents[pathComponents.length - 2];
      final int versionNumber =
          Strings.isEmpty(versionNumberString) ? 0 : Integer.parseInt(versionNumberString);
      parameters.setVersionNumber(versionNumber);

      // Component path is everything after pageMapName and before version
      final int start = pageMapName.length() + 1;
      final int end =
          requestString.length() - interfaceName.length() - versionNumberString.length() - 2;
      final String componentPath = requestString.substring(start, end);
      parameters.setComponentPath(componentPath);
    }
  }
  /**
   * Adds bookmarkable page related parameters (page alias and optionally page parameters). Any
   * bookmarkable page alias mount will override this method; hence if a mount is found, this method
   * will not be called.
   *
   * <p>If you override this method to behave different then also {@link #encode(RequestCycle,
   * IBookmarkablePageRequestTarget)} should be overridden to by in sync with that behaviour.
   *
   * @param request the incoming request
   * @param parameters the parameters object to set the found values on
   */
  protected void addBookmarkablePageParameters(
      final Request request, final RequestParameters parameters) {
    final String requestString =
        request.getParameter(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME);
    if (requestString != null) {
      final String[] components = Strings.split(requestString, Component.PATH_SEPARATOR);
      if (components.length != 2) {
        throw new WicketRuntimeException(
            "Invalid bookmarkablePage parameter: "
                + requestString
                + ", expected: 'pageMapName:pageClassName'");
      }

      // Extract any pagemap name
      final String pageMapName = components[0];
      parameters.setPageMapName(pageMapName.length() == 0 ? PageMap.DEFAULT_NAME : pageMapName);

      // Extract bookmarkable page class name
      final String pageClassName = components[1];
      parameters.setBookmarkablePageClass(pageClassName);
    }
  }