class AvailableColumnsModel {

    private static final int MAX_AVAILABLE_COLUMNS = 20;
    private final Set<Column> availableColumns = new HashSet<>();
    private final Set<Column> allKnownColumns = new HashSet<>();
    private final Table table;

    public AvailableColumnsModel(Table table) {
        this.table = table;
    }

    public boolean isColumnAvailable(Column column) {
        return availableColumns.contains(column);
    }

    /**
     * Add a column as available if it can be added.
     *
     * @param column Column to add
     * @return True if the column was successfully added, false otherwise (no more columns can be available)
     */
    public synchronized boolean addAvailableColumn(Column column) {
        if (canAddAvailableColumn()) {
            availableColumns.add(column);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Remove an available column from the model if possible.
     *
     * @param column Column to make not available
     * @return True if the column could be removed
     */
    public synchronized boolean removeAvailableColumn(Column column) {
        return availableColumns.remove(column);
    }

    /**
     * Clear all available columns
     */
    public synchronized void removeAllColumns() {
        availableColumns.clear();
    }

    /**
     * Indicates if more columns can be made available a the moment
     *
     * @return
     */
    public boolean canAddAvailableColumn() {
        return availableColumns.size() < MAX_AVAILABLE_COLUMNS;
    }

    /**
     * Return available columns, sorted by index
     *
     * @return
     */
    public Column[] getAvailableColumns() {
        List<Column> availableColumnsList = new ArrayList<>();
        for (Column column : table) {
            if (availableColumns.contains(column)) {
                availableColumnsList.add(column);
            }
        }
        return availableColumnsList.toArray(new Column[0]);
    }

    public int getAvailableColumnsCount() {
        return availableColumns.size();
    }

    /**
     * Syncronizes this AvailableColumnsModel to contain the table current columns, checking for deleted and new columns.
     */
    public synchronized void syncronizeTableColumns() {<FILL_FUNCTION_BODY>}
}

        Set<Column> availableColumnsCopy = new HashSet<>(availableColumns);

        removeAllColumns();

        //Detect new columns and make them available by default:
        //Also keep existing available columns as available.

        //Note: We need to remove all columns and add them all again because there could be a new column with the same title but different index 
        //if the old one with the same title was removed, and we should not keep the old column with same title.
        for (Column column : table) {
            if (availableColumnsCopy.contains(column) || !allKnownColumns.contains(column)) {
                allKnownColumns.add(column);

                addAvailableColumn(column);
            }
        }
    
<no_super_class>