/**
   * Parses the keywords and sets them into the data provider, forces update of the components that
   * need to as a result of the different filtering
   */
  private void updateFilter(AjaxRequestTarget target, String flatKeywords) {
    if ("".equals(flatKeywords)) {
      dataProvider.setKeywords(null);
      filter.setModelObject("");
      dataView.setCurrentPage(0);
    } else {
      String[] keywords = flatKeywords.split("\\s+");
      dataProvider.setKeywords(keywords);
      dataView.setCurrentPage(0);
    }
    pagerDelegate.updateMatched();
    navigatorTop.updateMatched();
    navigatorBottom.updateMatched();
    setSelection(false);

    target.addComponent(listContainer);
    target.addComponent(navigatorTop);
    target.addComponent(navigatorBottom);
  }
  /** Builds a new table panel */
  public GeoServerTablePanel(
      final String id, final GeoServerDataProvider<T> dataProvider, final boolean selectable) {
    super(id);
    this.dataProvider = dataProvider;

    // prepare the selection array
    selection = new boolean[DEFAULT_ITEMS_PER_PAGE];

    // layer container used for ajax-y udpates of the table
    listContainer = new WebMarkupContainer("listContainer");

    // build the filter form
    filterForm =
        new Form("filterForm") {
          @Override
          public void renderHead(IHeaderResponse response) {
            if (isRootForm()) return;

            // in subforms (on dialogs) the forms onsubmit doesn;t forward to the submit links
            // onclick, so we manually do it outselves
            String markupId = filterForm.getMarkupId();
            String js =
                "if (Wicket.Browser.isSafari() || Wicket.Browser.isIE()) {"
                    + "n = document.getElementById('"
                    + markupId
                    + "'); "
                    + "while (n.nodeName.toLowerCase() != 'form') { n = n.parentElement; }; "
                    + "n.setAttribute('onsubmit', \"return document.getElementById('"
                    + hiddenSubmit.getMarkupId()
                    + "').onclick();\");"
                    + "}";
            response.renderOnLoadJavascript(js);
          }
        };
    filterForm.setOutputMarkupId(true);
    add(filterForm);
    filterForm.add(filter = new TextField("filter", new Model()));
    filter.add(
        new SimpleAttributeModifier(
            "title",
            String.valueOf(new ResourceModel("GeoServerTablePanel.search", "Search").getObject())));
    filterForm.add(hiddenSubmit = hiddenSubmit());
    filterForm.setDefaultButton(hiddenSubmit);

    // setup the table
    listContainer.setOutputMarkupId(true);
    add(listContainer);
    dataView =
        new DataView("items", dataProvider) {

          @Override
          protected void populateItem(Item item) {
            final IModel itemModel = item.getModel();

            // odd/even style
            item.add(
                new SimpleAttributeModifier("class", item.getIndex() % 2 == 0 ? "even" : "odd"));

            // add row selector (visible only if selection is active)
            WebMarkupContainer cnt = new WebMarkupContainer("selectItemContainer");
            cnt.add(selectOneCheckbox(item));
            cnt.setVisible(selectable);
            item.add(cnt);

            // create one component per viewable property
            ListView items =
                new ListView("itemProperties", dataProvider.getVisibleProperties()) {

                  @Override
                  protected void populateItem(ListItem item) {
                    Property<T> property = (Property<T>) item.getModelObject();

                    Component component = getComponentForProperty("component", itemModel, property);

                    if (component == null) {
                      // show a plain label if the the subclass did not create any component
                      component = new Label("component", property.getModel(itemModel));
                    } else if (!"component".equals(component.getId())) {
                      // add some checks for the id, the error message
                      // that wicket returns in case of mismatch is not
                      // that helpful
                      throw new IllegalArgumentException(
                          "getComponentForProperty asked "
                              + "to build a component "
                              + "with id = 'component' "
                              + "for property '"
                              + property.getName()
                              + "', but got '"
                              + component.getId()
                              + "' instead");
                    }
                    item.add(component);
                    onPopulateItem(property, item);
                  }
                };
            items.setReuseItems(true);
            item.add(items);
          }
        };
    dataView.setItemReuseStrategy(ReuseIfModelsEqualStrategy.getInstance());
    listContainer.add(dataView);

    // add select all checkbox
    WebMarkupContainer cnt = new WebMarkupContainer("selectAllContainer");
    cnt.add(selectAll = selectAllCheckbox());
    cnt.setVisible(selectable);
    listContainer.add(cnt);

    // add the sorting links
    listContainer.add(
        new ListView("sortableLinks", dataProvider.getVisibleProperties()) {

          @Override
          protected void populateItem(ListItem item) {
            Property<T> property = (Property<T>) item.getModelObject();

            // build a sortable link if the property is sortable, a label otherwise
            IModel titleModel = getPropertyTitle(property);
            if (sortable && property.getComparator() != null) {
              Fragment f = new Fragment("header", "sortableHeader", item);
              AjaxLink link = sortLink(dataProvider, item);
              link.add(new Label("label", titleModel));
              f.add(link);
              item.add(f);
            } else {
              item.add(new Label("header", titleModel));
            }
          }
        });

    // add the paging navigator and set the items per page
    dataView.setItemsPerPage(DEFAULT_ITEMS_PER_PAGE);
    pagerDelegate = new PagerDelegate();

    filterForm.add(navigatorTop = new Pager("navigatorTop"));
    navigatorTop.setOutputMarkupId(true);
    add(navigatorBottom = new Pager("navigatorBottom"));
    navigatorBottom.setOutputMarkupId(true);
  }
 /** Sets back to the first page, clears the selection and */
 public void reset() {
   dataView.setCurrentPage(0);
   clearSelection();
   dataProvider.setSort(null);
 }