/** 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);
  }
  @Override
  protected void onInitialize(EmptyPlugin plugin, AbstractPluginBean pluginBean) {
    PageParameters params = getPageRequestParameters();
    if (params.isEmpty()) {
      setVisible(false);
      setResponsePage(ClassifiersPage.class);
      return;
    }

    final String classifierType = params.get(ClassifiersPanel.PARAM_CLASSIFIER_TYPE).toString();
    String parentClassifierItem = null;
    if (params.get(ClassifierConstants.PARENT_ITEM) != null) {
      parentClassifierItem = params.get(ClassifierConstants.PARENT_ITEM).toString();
    }

    // Add data container
    final DecoratedPagingNavigatorContainer<ClassifierItem> dataContainer =
        new DecoratedPagingNavigatorContainer<ClassifierItem>(
            "container", getCurrentRedirectLink());
    add(dataContainer);

    // Add data view
    final DataView<ClassifierItem> classifierDataView =
        new DataView<ClassifierItem>(
            "item-list", new ClassifierDataProvider(classifierType, parentClassifierItem)) {
          private static final long serialVersionUID = 1L;

          @Override
          protected void populateItem(Item<ClassifierItem> item) {
            ClassifierItem classifierItem = item.getModelObject();

            // Add link
            PageParameters pageParameters = new PageParameters();
            pageParameters.set(ClassifiersPanel.PARAM_CLASSIFIER_TYPE, classifierType);
            pageParameters.add(ClassifierConstants.PARENT_ITEM, classifierItem.getCode());
            BookmarkablePageLink<Void> link =
                new BookmarkablePageLink<Void>(
                    "link-item", ClassifiersItemPage.class, pageParameters);
            item.add(link);
            link.add(new Label("code", new Model<String>(classifierItem.getCode())));

            // Add name
            item.add(new Label("name", new Model<String>(classifierItem.getName())));
          }
        };
    dataContainer.addAbstractPageableView(classifierDataView);
    dataContainer.setVisible(true);
    classifierDataView.setItemReuseStrategy(ReuseIfModelsEqualStrategy.getInstance());

    // Create modal window to create new classifier
    final ModalWindow addNewClassifierModalWindow =
        new CustomModalWindow("modal-new-item", "title") {
          private static final long serialVersionUID = 1L;

          @Override
          protected void addComponentsToRefresh(java.util.List<Component> components) {
            components.add(dataContainer);
          };
        };
    addNewClassifierModalWindow.setContent(
        new NewClassifierItemPanel<ClassifierItem, Classifier>(
            addNewClassifierModalWindow, params));

    add(addNewClassifierModalWindow);

    // add create new classifier link
    add(
        new AjaxLink<Void>("link-add-new-item") {
          private static final long serialVersionUID = 1L;

          @Override
          public void onClick(AjaxRequestTarget target) {
            addNewClassifierModalWindow.show(target);
          }
        });
  }
 /**
  * Sets the item reuse strategy for the table. Should be {@link ReuseIfModelsEqualStrategy} if
  * you're building an editable table, {@link DefaultItemReuseStrategy} otherwise
  */
 public void setItemReuseStrategy(IItemReuseStrategy strategy) {
   dataView.setItemReuseStrategy(strategy);
 }