public LinksSelectorPanelAbstract(
      final String id,
      final String underlyingIdPrefix,
      final T model,
      final ComponentFactory factory) {
    super(id, model);

    componentType = factory.getComponentType();

    addAdditionalLinks(model);
    addUnderlyingViews(underlyingIdPrefix, model, factory);
  }
  private void addUnderlyingViews(
      final String underlyingIdPrefix, final T model, final ComponentFactory factory) {
    final List<ComponentFactory> componentFactories = findOtherComponentFactories(model, factory);

    final int selected = determineInitialFactory(componentFactories, model);

    final LinksSelectorPanelAbstract<T> selectorPanel = LinksSelectorPanelAbstract.this;

    // create all, hide the one not selected
    final Component[] underlyingViews = new Component[MAX_NUM_UNDERLYING_VIEWS];
    int i = 0;
    for (ComponentFactory componentFactory : componentFactories) {
      final String underlyingId = underlyingIdPrefix + "-" + i;

      final T emptyModel = dummyOf(model);
      Component underlyingView =
          componentFactory.createComponent(underlyingId, i == selected ? model : emptyModel);
      underlyingViews[i++] = underlyingView;
      selectorPanel.addOrReplace(underlyingView);
    }

    // hide any unused placeholders
    while (i < MAX_NUM_UNDERLYING_VIEWS) {
      String underlyingId = underlyingIdPrefix + "-" + i;
      permanentlyHide(underlyingId);
      i++;
    }

    // selector
    if (componentFactories.size() <= 1) {
      permanentlyHide(ID_VIEWS);
    } else {
      final Model<ComponentFactory> componentFactoryModel = new Model<ComponentFactory>();

      selectorPanel.selectedComponentFactory = componentFactories.get(selected);
      componentFactoryModel.setObject(selectorPanel.selectedComponentFactory);

      final WebMarkupContainer views = new WebMarkupContainer(ID_VIEWS);

      final WebMarkupContainer container = new WebMarkupContainer(ID_VIEW_LIST);

      views.addOrReplace(container);
      views.setOutputMarkupId(true);

      this.setOutputMarkupId(true);

      final ListView<ComponentFactory> listView =
          new ListView<ComponentFactory>(ID_VIEW_ITEM, componentFactories) {

            private static final long serialVersionUID = 1L;

            @Override
            protected void populateItem(ListItem<ComponentFactory> item) {

              final int underlyingViewNum = item.getIndex();

              final ComponentFactory componentFactory = item.getModelObject();
              final AbstractLink link =
                  new AjaxLink<Void>(ID_VIEW_LINK) {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public void onClick(AjaxRequestTarget target) {

                      for (int i = 0; i < MAX_NUM_UNDERLYING_VIEWS; i++) {
                        final Component component = underlyingViews[i];
                        T dummyModel = dummyOf(model);

                        if (component != null) {
                          final boolean isSelected = i == underlyingViewNum;
                          applyCssVisibility(component, isSelected);
                          component.setDefaultModel(isSelected ? model : dummyModel);
                        }
                      }
                      selectorPanel.selectedComponentFactory = componentFactory;
                      target.add(selectorPanel, views);
                    }
                  };
              String name = nameFor(componentFactory);
              Label viewTitleLabel = new Label(ID_VIEW_TITLE, name);
              viewTitleLabel.add(new CssClassAppender(StringUtils.toLowerDashed(name)));
              link.add(viewTitleLabel);
              item.add(link);

              link.setEnabled(componentFactory != selectorPanel.selectedComponentFactory);
            }

            private String nameFor(final ComponentFactory componentFactory) {
              return componentFactory instanceof CollectionContentsAsUnresolvedPanelFactory
                  ? "hide"
                  : componentFactory.getName();
            }
          };
      container.add(listView);
      addOrReplace(views);
    }

    for (i = 0; i < MAX_NUM_UNDERLYING_VIEWS; i++) {
      Component component = underlyingViews[i];
      if (component != null) {
        if (i != selected) {
          component.add(new AttributeAppender("class", " " + INVISIBLE_CLASS));
        }
      }
    }
  }