class AbstractDialogBuilder<B, T extends DialogWindow> {
    protected String title;
    protected String description;
    protected Set<Window.Hint> extraWindowHints;

    /**
     * Default constructor for a dialog builder
     * @param title Title to assign to the dialog
     */
    public AbstractDialogBuilder(String title) {
        this.title = title;
        this.description = null;
        this.extraWindowHints = Collections.singleton(Window.Hint.CENTERED);
    }

    /**
     * Changes the title of the dialog
     * @param title New title
     * @return Itself
     */
    public B setTitle(String title) {<FILL_FUNCTION_BODY>}

    /**
     * Returns the title that the built dialog will have
     * @return Title that the built dialog will have
     */
    public String getTitle() {
        return title;
    }

    /**
     * Changes the description of the dialog
     * @param description New description
     * @return Itself
     */
    public B setDescription(String description) {
        this.description = description;
        return self();
    }

    /**
     * Returns the description that the built dialog will have
     * @return Description that the built dialog will have
     */
    public String getDescription() {
        return description;
    }

    /**
     * Assigns a set of extra window hints that you want the built dialog to have
     * @param extraWindowHints Window hints to assign to the window in addition to the ones the builder will put
     * @return Itself
     */
    public B setExtraWindowHints(Set<Window.Hint> extraWindowHints) {
        this.extraWindowHints = extraWindowHints;
        return self();
    }

    /**
     * Returns the list of extra window hints that will be assigned to the window when built
     * @return List of extra window hints that will be assigned to the window when built
     */
    public Set<Window.Hint> getExtraWindowHints() {
        return extraWindowHints;
    }

    /**
     * Helper method for casting this to {@code type} parameter {@code B}
     * @return {@code this} as {@code B}
     */
    protected abstract B self();

    /**
     * Builds the dialog according to the builder implementation
     * @return New dialog object
     */
    protected abstract T buildDialog();

    /**
     * Builds a new dialog following the specifications of this builder
     * @return New dialog built following the specifications of this builder
     */
    public final T build() {
        T dialog = buildDialog();
        if(!extraWindowHints.isEmpty()) {
            Set<Window.Hint> combinedHints = new HashSet<>(dialog.getHints());
            combinedHints.addAll(extraWindowHints);
            dialog.setHints(combinedHints);
        }
        return dialog;
    }
}

        if(title == null) {
            title = "";
        }
        this.title = title;
        return self();
    
<no_super_class>