@SuppressWarnings("null")
  @Override
  protected void showInputForm(
      @Nonnull final WebPageExecutionContext aWPEC,
      @Nullable final IUser aSelectedObject,
      @Nonnull final HCForm aForm,
      final boolean bEdit,
      final boolean bCopy,
      @Nonnull final FormErrors aFormErrors) {
    if (bEdit && !isEditAllowed(aSelectedObject)) throw new IllegalStateException("Won't work!");

    final boolean bIsAdministrator = aSelectedObject != null && aSelectedObject.isAdministrator();
    final Locale aDisplayLocale = aWPEC.getDisplayLocale();
    final AccessManager aMgr = AccessManager.getInstance();
    final IHCTableForm<?> aTable =
        aForm.addAndReturnChild(
            getStyler().createTableForm(new HCCol(170), HCCol.star(), new HCCol(20)));
    aTable.setSpanningHeaderContent(
        bEdit
            ? EText.TITLE_EDIT.getDisplayTextWithArgs(
                aDisplayLocale, SecurityUI.getUserDisplayName(aSelectedObject, aDisplayLocale))
            : EText.TITLE_CREATE.getDisplayText(aDisplayLocale));

    if (!useEmailAddressAsLoginName()) {
      final String sLoginName = EText.LABEL_LOGINNAME.getDisplayText(aDisplayLocale);
      aTable
          .createItemRow()
          .setLabelMandatory(sLoginName)
          .setCtrl(
              new HCEdit(
                      new RequestField(
                          FIELD_LOGINNAME,
                          aSelectedObject == null ? null : aSelectedObject.getLoginName()))
                  .setPlaceholder(sLoginName))
          .setErrorList(aFormErrors.getListOfField(FIELD_LOGINNAME));
    }

    {
      final String sFirstName = EText.LABEL_FIRSTNAME.getDisplayText(aDisplayLocale);
      aTable
          .createItemRow()
          .setLabel(sFirstName)
          .setCtrl(
              new HCEdit(
                      new RequestField(
                          FIELD_FIRSTNAME,
                          aSelectedObject == null ? null : aSelectedObject.getFirstName()))
                  .setPlaceholder(sFirstName))
          .setErrorList(aFormErrors.getListOfField(FIELD_FIRSTNAME));
    }

    {
      final String sLastName = EText.LABEL_LASTNAME.getDisplayText(aDisplayLocale);
      aTable
          .createItemRow()
          .setLabel(sLastName, isLastNameMandatory() ? ELabelType.MANDATORY : ELabelType.OPTIONAL)
          .setCtrl(
              new HCEdit(
                      new RequestField(
                          FIELD_LASTNAME,
                          aSelectedObject == null ? null : aSelectedObject.getLastName()))
                  .setPlaceholder(sLastName))
          .setErrorList(aFormErrors.getListOfField(FIELD_LASTNAME));
    }

    {
      final String sEmail = EText.LABEL_EMAIL.getDisplayText(aDisplayLocale);
      aTable
          .createItemRow()
          .setLabel(sEmail, isEmailMandatory() ? ELabelType.MANDATORY : ELabelType.OPTIONAL)
          .setCtrl(
              new HCEdit(
                      new RequestField(
                          FIELD_EMAILADDRESS,
                          aSelectedObject == null ? null : aSelectedObject.getEmailAddress()))
                  .setPlaceholder(sEmail))
          .setErrorList(aFormErrors.getListOfField(FIELD_EMAILADDRESS));
    }

    if (!bEdit) {
      // Password is only shown on creation of a new user
      final boolean bHasAnyPasswordConstraint =
          GlobalPasswordSettings.getPasswordConstraintList().hasConstraints();

      final String sPassword = EText.LABEL_PASSWORD.getDisplayText(aDisplayLocale);
      aTable
          .createItemRow()
          .setLabel(
              sPassword, bHasAnyPasswordConstraint ? ELabelType.MANDATORY : ELabelType.OPTIONAL)
          .setCtrl(new HCEditPassword(FIELD_PASSWORD).setPlaceholder(sPassword))
          .setNote(SecurityUI.createPasswordConstraintTip(aDisplayLocale))
          .setErrorList(aFormErrors.getListOfField(FIELD_PASSWORD));

      final String sPasswordConfirm = EText.LABEL_PASSWORD_CONFIRM.getDisplayText(aDisplayLocale);
      aTable
          .createItemRow()
          .setLabel(
              sPasswordConfirm,
              bHasAnyPasswordConstraint ? ELabelType.MANDATORY : ELabelType.OPTIONAL)
          .setCtrl(new HCEditPassword(FIELD_PASSWORD_CONFIRM).setPlaceholder(sPasswordConfirm))
          .setNote(SecurityUI.createPasswordConstraintTip(aDisplayLocale))
          .setErrorList(aFormErrors.getListOfField(FIELD_PASSWORD_CONFIRM));
    }

    if (bIsAdministrator) {
      // Cannot edit enabled state of administrator
      aTable
          .createItemRow()
          .setLabel(EText.LABEL_ENABLED.getDisplayText(aDisplayLocale))
          .setCtrl(EWebBasicsText.getYesOrNo(aSelectedObject.isEnabled(), aDisplayLocale));
    } else {
      aTable
          .createItemRow()
          .setLabelMandatory(EText.LABEL_ENABLED.getDisplayText(aDisplayLocale))
          .setCtrl(
              new HCCheckBox(
                  new RequestFieldBoolean(
                      FIELD_ENABLED,
                      aSelectedObject == null ? DEFAULT_ENABLED : aSelectedObject.isEnabled())))
          .setErrorList(aFormErrors.getListOfField(FIELD_ENABLED));
    }

    {
      final Collection<String> aUserGroupIDs =
          aSelectedObject == null
              ? aWPEC.getAttrs(FIELD_USERGROUPS)
              : aMgr.getAllUserGroupIDsWithAssignedUser(aSelectedObject.getID());
      final UserGroupForUserSelect aSelect =
          new UserGroupForUserSelect(
              new RequestField(FIELD_USERGROUPS), aDisplayLocale, aUserGroupIDs);
      aTable
          .createItemRow()
          .setLabelMandatory(EText.LABEL_USERGROUPS_0.getDisplayText(aDisplayLocale))
          .setCtrl(aSelect)
          .setErrorList(aFormErrors.getListOfField(FIELD_USERGROUPS));
      if (bIsAdministrator) {
        // Cannot edit user groups of administrator
        aSelect.setReadonly(true);
      }
      showInputFormModifyUserGroupSelect(aSelect);
    }

    // Custom overridable
    showInputFormEnd(aWPEC, aSelectedObject, aForm, bEdit, bCopy, aFormErrors, aTable);
  }
  @Override
  @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE")
  protected void showSelectedObject(
      @Nonnull final WebPageExecutionContext aWPEC, @Nonnull final IUser aSelectedObject) {
    final HCNodeList aNodeList = aWPEC.getNodeList();
    final Locale aDisplayLocale = aWPEC.getDisplayLocale();
    final AccessManager aMgr = AccessManager.getInstance();
    final IHCTableFormView<?> aTable =
        aNodeList.addAndReturnChild(getStyler().createTableFormView(new HCCol(170), HCCol.star()));
    aTable.setSpanningHeaderContent(
        EText.HEADER_DETAILS.getDisplayTextWithArgs(
            aDisplayLocale, SecurityUI.getUserDisplayName(aSelectedObject, aDisplayLocale)));
    onShowSelectedObjectTableStart(aTable, aSelectedObject, aDisplayLocale);
    if (!useEmailAddressAsLoginName()) {
      aTable
          .createItemRow()
          .setLabel(EText.LABEL_LOGINNAME.getDisplayText(aDisplayLocale))
          .setCtrl(aSelectedObject.getLoginName());
    }
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_FIRSTNAME.getDisplayText(aDisplayLocale))
        .setCtrl(aSelectedObject.getFirstName());
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_LASTNAME.getDisplayText(aDisplayLocale))
        .setCtrl(aSelectedObject.getLastName());
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_EMAIL.getDisplayText(aDisplayLocale))
        .setCtrl(getStyler().createEmailLink(aSelectedObject.getEmailAddress()));
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_ENABLED.getDisplayText(aDisplayLocale))
        .setCtrl(EWebBasicsText.getYesOrNo(aSelectedObject.isEnabled(), aDisplayLocale));
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_DELETED.getDisplayText(aDisplayLocale))
        .setCtrl(EWebBasicsText.getYesOrNo(aSelectedObject.isDeleted(), aDisplayLocale));
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_LAST_LOGIN.getDisplayText(aDisplayLocale))
        .setCtrl(
            aSelectedObject.getLastLoginDateTime() != null
                ? new HCTextNode(
                    PDTToString.getAsString(aSelectedObject.getLastLoginDateTime(), aDisplayLocale))
                : HCEM.create(EText.LABEL_LAST_LOGIN_NEVER.getDisplayText(aDisplayLocale)));
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_LOGIN_COUNT.getDisplayText(aDisplayLocale))
        .setCtrl(Integer.toString(aSelectedObject.getLoginCount()));
    aTable
        .createItemRow()
        .setLabel(EText.LABEL_CONSECUTIVE_FAILED_LOGIN_COUNT.getDisplayText(aDisplayLocale))
        .setCtrl(Integer.toString(aSelectedObject.getConsecutiveFailedLoginCount()));

    // user groups
    final Collection<IUserGroup> aUserGroups =
        aMgr.getAllUserGroupsWithAssignedUser(aSelectedObject.getID());
    if (aUserGroups.isEmpty()) {
      aTable
          .createItemRow()
          .setLabel(EText.LABEL_USERGROUPS_0.getDisplayText(aDisplayLocale))
          .setCtrl(HCEM.create(EText.NONE_DEFINED.getDisplayText(aDisplayLocale)));
    } else {
      final HCNodeList aUserGroupUI = new HCNodeList();
      for (final IUserGroup aUserGroup :
          ContainerHelper.getSorted(aUserGroups, new ComparatorHasName<IUserGroup>(aDisplayLocale)))
        aUserGroupUI.addChild(HCDiv.create(aUserGroup.getName()));
      aTable
          .createItemRow()
          .setLabel(
              EText.LABEL_USERGROUPS_N.getDisplayTextWithArgs(
                  aDisplayLocale, Integer.toString(aUserGroups.size())))
          .setCtrl(aUserGroupUI);
    }

    // roles
    final Set<IRole> aUserRoles = aMgr.getAllUserRoles(aSelectedObject.getID());
    if (aUserRoles.isEmpty()) {
      aTable
          .createItemRow()
          .setLabel(EText.LABEL_ROLES_0.getDisplayText(aDisplayLocale))
          .setCtrl(HCEM.create(EText.NONE_DEFINED.getDisplayText(aDisplayLocale)));
    } else {
      final HCNodeList aRoleUI = new HCNodeList();
      for (final IRole aRole :
          ContainerHelper.getSorted(aUserRoles, new ComparatorHasName<IRole>(aDisplayLocale)))
        aRoleUI.addChild(HCDiv.create(aRole.getName()));
      aTable
          .createItemRow()
          .setLabel(
              EText.LABEL_ROLES_N.getDisplayTextWithArgs(
                  aDisplayLocale, Integer.toString(aUserRoles.size())))
          .setCtrl(aRoleUI);
    }

    // custom attributes
    final Map<String, Object> aCustomAttrs = aSelectedObject.getAllAttributes();

    // Callback
    final Set<String> aHandledAttrs =
        showCustomAttrsOfSelectedObject(aSelectedObject, aCustomAttrs, aTable, aDisplayLocale);

    if (!aCustomAttrs.isEmpty()) {
      final IHCTable<?> aAttrTable = getStyler().createTable(new HCCol(170), HCCol.star());
      aAttrTable
          .addHeaderRow()
          .addCells(
              EText.HEADER_NAME.getDisplayText(aDisplayLocale),
              EText.HEADER_VALUE.getDisplayText(aDisplayLocale));
      for (final Map.Entry<String, Object> aEntry : aCustomAttrs.entrySet()) {
        final String sName = aEntry.getKey();
        if (aHandledAttrs == null || !aHandledAttrs.contains(sName)) {
          final String sValue = String.valueOf(aEntry.getValue());
          aAttrTable.addBodyRow().addCells(sName, sValue);
        }
      }

      // Maybe all custom attributes where handled in
      // showCustomAttrsOfSelectedObject
      if (aAttrTable.hasBodyRows())
        aTable
            .createItemRow()
            .setLabel(EText.LABEL_ATTRIBUTES.getDisplayText(aDisplayLocale))
            .setCtrl(aAttrTable);
    }

    // Callback
    onShowSelectedObjectTableEnd(aTable, aSelectedObject, aDisplayLocale);
  }