/*
 * Copyright 2000-2014 Vaadin Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.vaadin.ui;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.ContainerOrderedWrapper;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.ConverterUtil;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.DataBoundTransferable;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.event.ItemClickEvent.ItemClickNotifier;
import com.vaadin.event.MouseEvents.ClickEvent;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.server.KeyMapper;
import com.vaadin.server.LegacyCommunicationManager;
import com.vaadin.server.LegacyPaint;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.server.Resource;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.MultiSelectMode;
import com.vaadin.shared.ui.table.TableConstants;

// TODO: Auto-generated Javadoc
/**
 * <p>
 * <code>CustomTable</code> is used for representing data or components in a
 * pageable and selectable CustomTable.
 * 
 * 
 * <p>
 * Scalability of the CustomTable is largely dictated by the container. A table
 * does not have a limit for the number of items and is just as fast with
 * hundreds of thousands of items as with just a few. The current GWT
 * implementation with scrolling however limits the number of rows to around
 * 500000, depending on the browser and the pixel height of rows.
 * 
 * 
 * <p>
 * Components in a CustomTable will not have their caption nor icon rendered.
 * 
 * 
 * @author Vaadin Ltd.
 * @since 3.0
 */
@SuppressWarnings({ "deprecation" })
public class CustomTable extends AbstractSelect implements Action.Container,
        Container.Ordered, Container.Sortable, ItemClickNotifier, DragSource,
        DropTarget, HasComponents {

    /**
	 * 
	 */
	private static final long serialVersionUID = 6393600859108457264L;

	/** The logger. */
    private transient Logger logger = null;

    /**
     * Modes that CustomTable support as drag sourse.
     */
    public enum TableDragMode {
        /**
         * CustomTable does not start drag and drop events. HTM5 style events
         * started by browser may still happen.
         */
        NONE,
        /**
         * CustomTable starts drag with a one row only.
         */
        ROW,
        /**
         * CustomTable drags selected rows, if drag starts on a selected rows.
         * Else it starts like in ROW mode. Note, that in Transferable there
         * will still be only the row on which the drag started, other dragged
         * rows need to be checked from the source CustomTable.
         */
        MULTIROW
    }

    /** The Constant CELL_KEY. */
    protected static final int CELL_KEY = 0;

    /** The Constant CELL_HEADER. */
    protected static final int CELL_HEADER = 1;

    /** The Constant CELL_ICON. */
    protected static final int CELL_ICON = 2;

    /** The Constant CELL_ITEMID. */
    protected static final int CELL_ITEMID = 3;

    /** The Constant CELL_GENERATED_ROW. */
    protected static final int CELL_GENERATED_ROW = 4;

    /** The Constant CELL_FIRSTCOL. */
    protected static final int CELL_FIRSTCOL = 5;

    /** The Enum Align.
	 */
    public enum Align {
        /**
         * Left column alignment. <b>This is the default behaviour. </b>
         */
        LEFT("b"),

        /**
         * Center column alignment.
         */
        CENTER("c"),

        /**
         * Right column alignment.
         */
        RIGHT("e");

        /** The alignment. */
        private String alignment;

        /** Instantiates a new align.
		 *
		 * @param alignment
		 *            the alignment
		 */
        private Align(String alignment) {
            this.alignment = alignment;
        }

        /* (non-Javadoc)
         * @see java.lang.Enum#toString()
         */
        @Override
        public String toString() {
            return alignment;
        }

        /** Convert string to align.
		 *
		 * @param string
		 *            the string
		 * @return the align
		 */
        public Align convertStringToAlign(String string) {
            if (string == null) {
                return null;
            }
            if (string.equals("b")) {
                return Align.LEFT;
            } else if (string.equals("c")) {
                return Align.CENTER;
            } else if (string.equals("e")) {
                return Align.RIGHT;
            } else {
                return null;
            }
        }
    }

    /** The Constant ALIGN_LEFT.
	 *
	 * @deprecated As of 7.0, use {@link Align#LEFT} instead
	 */
    @Deprecated
    public static final Align ALIGN_LEFT = Align.LEFT;

    /** The Constant ALIGN_CENTER.
	 *
	 * @deprecated As of 7.0, use {@link Align#CENTER} instead
	 */
    @Deprecated
    public static final Align ALIGN_CENTER = Align.CENTER;

    /** The Constant ALIGN_RIGHT.
	 *
	 * @deprecated As of 7.0, use {@link Align#RIGHT} instead
	 */
    @Deprecated
    public static final Align ALIGN_RIGHT = Align.RIGHT;

    /** The Enum ColumnHeaderMode.
	 */
    public enum ColumnHeaderMode {
        /**
         * Column headers are hidden.
         */
        HIDDEN,
        /**
         * Property ID:s are used as column headers.
         */
        ID,
        /**
         * Column headers are explicitly specified with
         * {@link #setColumnHeaders(String[])}.
         */
        EXPLICIT,
        /**
         * Column headers are explicitly specified with
         * {@link #setColumnHeaders(String[])}. If a header is not specified for
         * a given property, its property id is used instead.
         * <p>
         * <b>This is the default behavior. </b>
         */
        EXPLICIT_DEFAULTS_ID
    }

    /** The Constant COLUMN_HEADER_MODE_HIDDEN.
	 *
	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#HIDDEN} instead
	 */
    @Deprecated
    public static final ColumnHeaderMode COLUMN_HEADER_MODE_HIDDEN = ColumnHeaderMode.HIDDEN;

    /** The Constant COLUMN_HEADER_MODE_ID.
	 *
	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#ID} instead
	 */
    @Deprecated
    public static final ColumnHeaderMode COLUMN_HEADER_MODE_ID = ColumnHeaderMode.ID;

    /** The Constant COLUMN_HEADER_MODE_EXPLICIT.
	 *
	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#EXPLICIT} instead
	 */
    @Deprecated
    public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT = ColumnHeaderMode.EXPLICIT;

    /** The Constant COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID.
	 *
	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#EXPLICIT_DEFAULTS_ID}
	 *             instead
	 */
    @Deprecated
    public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID;

    /** The Enum RowHeaderMode.
	 */
    public enum RowHeaderMode {
        /**
         * Row caption mode: The row headers are hidden. <b>This is the default
         * mode. </b>
         */
        HIDDEN(null),
        /**
         * Row caption mode: Items Id-objects toString is used as row caption.
         */
        ID(ItemCaptionMode.ID),
        /**
         * Row caption mode: Item-objects toString is used as row caption.
         */
        ITEM(ItemCaptionMode.ITEM),
        /**
         * Row caption mode: Index of the item is used as item caption. The
         * index mode can only be used with the containers implementing the
         * {@link com.vaadin.data.Container.Indexed} interface.
         */
        INDEX(ItemCaptionMode.INDEX),
        /**
         * Row caption mode: Item captions are explicitly specified, but if the
         * caption is missing, the item id objects <code>toString()</code> is
         * used instead.
         */
        EXPLICIT_DEFAULTS_ID(ItemCaptionMode.EXPLICIT_DEFAULTS_ID),
        /**
         * Row caption mode: Item captions are explicitly specified.
         */
        EXPLICIT(ItemCaptionMode.EXPLICIT),
        /**
         * Row caption mode: Only icons are shown, the captions are hidden.
         */
        ICON_ONLY(ItemCaptionMode.ICON_ONLY),
        /**
         * Row caption mode: Item captions are read from property specified with
         * {@link #setItemCaptionPropertyId(Object)}.
         */
        PROPERTY(ItemCaptionMode.PROPERTY);

        /** The mode. */
        ItemCaptionMode mode;

        /** Instantiates a new row header mode.
		 *
		 * @param mode
		 *            the mode
		 */
        private RowHeaderMode(ItemCaptionMode mode) {
            this.mode = mode;
        }

        /** Gets the item caption mode.
		 *
		 * @return the item caption mode
		 */
        public ItemCaptionMode getItemCaptionMode() {
            return mode;
        }
    }

    /** The Constant ROW_HEADER_MODE_HIDDEN.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#HIDDEN} instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_HIDDEN = RowHeaderMode.HIDDEN;

    /** The Constant ROW_HEADER_MODE_ID.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#ID} instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_ID = RowHeaderMode.ID;

    /** The Constant ROW_HEADER_MODE_ITEM.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#ITEM} instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_ITEM = RowHeaderMode.ITEM;

    /** The Constant ROW_HEADER_MODE_INDEX.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#INDEX} instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_INDEX = RowHeaderMode.INDEX;

    /** The Constant ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#EXPLICIT_DEFAULTS_ID}
	 *             instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = RowHeaderMode.EXPLICIT_DEFAULTS_ID;

    /** The Constant ROW_HEADER_MODE_EXPLICIT.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#EXPLICIT} instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT = RowHeaderMode.EXPLICIT;

    /** The Constant ROW_HEADER_MODE_ICON_ONLY.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#ICON_ONLY} instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_ICON_ONLY = RowHeaderMode.ICON_ONLY;

    /** The Constant ROW_HEADER_MODE_PROPERTY.
	 *
	 * @deprecated As of 7.0, use {@link RowHeaderMode#PROPERTY} instead
	 */
    @Deprecated
    public static final RowHeaderMode ROW_HEADER_MODE_PROPERTY = RowHeaderMode.PROPERTY;

    /**
     * The default rate that table caches rows for smooth scrolling.
     */
    private static final double CACHE_RATE_DEFAULT = 2;

    /** The Constant ROW_HEADER_COLUMN_KEY. */
    private static final String ROW_HEADER_COLUMN_KEY = "0";
    
    /** The Constant ROW_HEADER_FAKE_PROPERTY_ID. */
    private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new UniqueSerializable() {

		/**
		 * 
		 */
		private static final long serialVersionUID = 5428814178809766481L;
    };

    /* Private table extensions to Select */

    /**
     * True if column collapsing is allowed.
     */
    private boolean columnCollapsingAllowed = false;

    /**
     * True if reordering of columns is allowed on the client side.
     */
    private boolean columnReorderingAllowed = false;

    /**
     * Keymapper for column ids.
     */
    protected final KeyMapper<Object> columnIdMap = new KeyMapper<>();

    /**
     * Holds visible column propertyIds - in order.
     */
    private LinkedList<Object> visibleColumns = new LinkedList<>();

    /**
     * Holds noncollapsible columns.
     */
    private HashSet<Object> noncollapsibleColumns = new HashSet<>();

    /**
     * Holds propertyIds of currently collapsed columns.
     */
    private final HashSet<Object> collapsedColumns = new HashSet<>();

    /**
     * Holds headers for visible columns (by propertyId).
     */
    private final HashMap<Object, String> columnHeaders = new HashMap<>();

    /**
     * Holds footers for visible columns (by propertyId).
     */
    private final HashMap<Object, String> columnFooters = new HashMap<>();

    /**
     * Holds icons for visible columns (by propertyId).
     */
    private final HashMap<Object, Resource> columnIcons = new HashMap<>();

    /**
     * Holds alignments for visible columns (by propertyId).
     */
    private HashMap<Object, Align> columnAlignments = new HashMap<>();

    /**
     * Holds column widths in pixels for visible columns (by propertyId).
     */
    private final HashMap<Object, Integer> columnWidths = new HashMap<>();

    /**
     * Holds column expand rations for visible columns (by propertyId).
     */
    private final HashMap<Object, Float> columnExpandRatios = new HashMap<>();

    /** Holds column generators. */
    private final HashMap<Object, ColumnGenerator> columnGenerators = new LinkedHashMap<>();

    /**
     * Holds value of property pageLength. 0 disables paging.
     */
    private int pageLength = 15;

    /**
     * Id the first item on the current page.
     */
    private Object currentPageFirstItemId = null;

    /**
     * Index of the first item on the current page.
     */
    private int currentPageFirstItemIndex = 0;

    /**
     * Index of the "first" item on the last page if a user has used
     * setCurrentPageFirstItemIndex to scroll down. -1 if not set.
     */
    private int currentPageFirstItemIndexOnLastPage = -1;

    /**
     * Holds value of property selectable.
     */
    private boolean selectable = false;

    /**
     * Holds value of property columnHeaderMode.
     */
    private ColumnHeaderMode columnHeaderMode = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID;

    /**
     * Holds value of property rowHeaderMode.
     */
    private RowHeaderMode rowHeaderMode = RowHeaderMode.EXPLICIT_DEFAULTS_ID;

    /** Should the CustomTable footer be visible?. */
    private boolean columnFootersVisible = false;

    /**
     * Page contents buffer used in buffered mode.
     */
    private Object[][] pageBuffer = null;

    /**
     * Set of properties listened - the list is kept to release the listeners
     * later.
     */
    private HashSet<Property<?>> listenedProperties = null;

    /**
     * Set of visible components - the is used for needsRepaint calculation.
     */
    protected HashSet<Component> visibleComponents = null;

    /**
     * List of action handlers.
     */
    private LinkedList<Handler> actionHandlers = null;

    /**
     * Action mapper.
     */
    private KeyMapper<Action> actionMapper = null;

    /**
     * CustomTable cell editor factory.
     */
    private TableFieldFactory fieldFactory = DefaultFieldFactory.get();

    /**
     * Is table editable.
     */
    private boolean editable = false;

    /**
     * Current sorting direction.
     */
    private boolean sortAscending = true;

    /**
     * Currently table is sorted on this propertyId.
     */
    private Object sortContainerPropertyId = null;

    /**
     * Is table sorting by the user enabled.
     */
    private boolean sortEnabled = true;

    /**
     * Number of rows explicitly requested by the client to be painted on next
     * paint. This is -1 if no request by the client is made. Painting the
     * component will automatically reset this to -1.
     */
    private int reqRowsToPaint = -1;

    /**
     * Index of the first rows explicitly requested by the client to be painted.
     * This is -1 if no request by the client is made. Painting the component
     * will automatically reset this to -1.
     */
    private int reqFirstRowToPaint = -1;

    /** The first to be rendered in client. */
    private int firstToBeRenderedInClient = -1;

    /** The last to be rendered in client. */
    private int lastToBeRenderedInClient = -1;

    /** The is content refreshes enabled. */
    private boolean isContentRefreshesEnabled = true;

    /** The page buffer first index. */
    private int pageBufferFirstIndex;

    /** The container change to be rendered. */
    private boolean containerChangeToBeRendered = false;

    /** CustomTable cell specific style generator. */
    private CellStyleGenerator cellStyleGenerator = null;

    /** CustomTable cell specific tooltip generator. */
    private ItemDescriptionGenerator itemDescriptionGenerator;

    /** The always recalculate column widths. */
    /*
     * EXPERIMENTAL feature: will tell the client to re-calculate column widths
     * if set to true. Currently no setter: extend to enable.
     */
    protected boolean alwaysRecalculateColumnWidths = false;

    /** The cache rate. */
    private double cacheRate = CACHE_RATE_DEFAULT;

    /** The drag mode. */
    private TableDragMode dragMode = TableDragMode.NONE;

    /** The drop handler. */
    private DropHandler dropHandler;

    /** The multi select mode. */
    private MultiSelectMode multiSelectMode = MultiSelectMode.DEFAULT;

    /** The row cache invalidated. */
    private boolean rowCacheInvalidated;

    /** The row generator. */
    private RowGenerator rowGenerator = null;

    /** The associated properties. */
    private final Map<Field<?>, Property<?>> associatedProperties = new HashMap<>();

    /** The painted. */
    private boolean painted = false;

    /** The property value converters. */
    private HashMap<Object, Converter<String, Object>> propertyValueConverters = new HashMap<>();

    /**
     * Set to true if the client-side should be informed that the key mapper has
     * been reset so it can avoid sending back references to keys that are no
     * longer present.
     */
    private boolean keyMapperReset;

    /** The exceptions during cache population. */
    private List<Throwable> exceptionsDuringCachePopulation = new ArrayList<>();

    /** The is being painted. */
    private boolean isBeingPainted;

    /* CustomTable constructors */

    /**
     * Creates a new empty table.
     */
    public CustomTable() {
        setRowHeaderMode(ROW_HEADER_MODE_HIDDEN);
    }

    /** Creates a new empty table with caption.
	 *
	 * @param caption
	 *            the caption
	 */
    public CustomTable(String caption) {
        this();
        setCaption(caption);
    }

    /** Creates a new table with caption and connect it to a Container.
	 *
	 * @param caption
	 *            the caption
	 * @param dataSource
	 *            the data source
	 */
    public CustomTable(String caption, Container dataSource) {
        this();
        setCaption(caption);
        setContainerDataSource(dataSource);
    }

    /* CustomTable functionality */

    /**
     * Gets the array of visible column id:s, including generated columns.
     * 
     * <p>
     * The columns are show in the order of their appearance in this array.
     * 
     * 
     * @return an array of currently visible propertyIds and generated column
     *         ids.
     */
    public Object[] getVisibleColumns() {
        if (visibleColumns == null) {
            return null;
        }
        return visibleColumns.toArray();
    }

    /**
     * Sets the array of visible column property id:s.
     * 
     * <p>
     * The columns are show in the order of their appearance in this array.
     * 
     * 
     * @param visibleColumns
     *            the Array of shown property id:s.
     */
    public void setVisibleColumns(Object... visibleColumns) {

        // Visible columns must exist
        if (visibleColumns == null) {
            throw new NullPointerException(
                    "Can not set visible columns to null value");
        }

        final LinkedList<Object> newVC = new LinkedList<>();

        // Checks that the new visible columns contains no nulls, properties
        // exist and that there are no duplicates before adding them to newVC.
        final Collection<?> properties = getContainerPropertyIds();
        for (int i = 0; i < visibleColumns.length; i++) {
            if (visibleColumns[i] == null) {
                throw new NullPointerException("Ids must be non-nulls");
            } else if (!properties.contains(visibleColumns[i])
                    && !columnGenerators.containsKey(visibleColumns[i])) {
                throw new IllegalArgumentException(
                        "Ids must exist in the Container or as a generated column, missing id: "
                                + visibleColumns[i]);
            } else if (newVC.contains(visibleColumns[i])) {
                throw new IllegalArgumentException(
                        "Ids must be unique, duplicate id: "
                                + visibleColumns[i]);
            } else {
                newVC.add(visibleColumns[i]);
            }
        }

        // Removes alignments, icons and headers from hidden columns
        if (this.visibleColumns != null) {
            boolean disabledHere = disableContentRefreshing();
            try {
                for (final Iterator<Object> i = this.visibleColumns.iterator(); i
                        .hasNext();) {
                    final Object col = i.next();
                    if (!newVC.contains(col)) {
                        setColumnHeader(col, null);
                        setColumnAlignment(col, (Align) null);
                        setColumnIcon(col, null);
                    }
                }
            } finally {
                if (disabledHere) {
                    enableContentRefreshing(false);
                }
            }
        }

        this.visibleColumns = newVC;

        // Assures visual refresh
        refreshRowCache();
    }

    /**
     * Gets the headers of the columns.
     * 
     * <p>
     * The headers match the property id:s given my the set visible column
     * headers. The table must be set in either
     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the
     * headers. In the defaults mode any nulls in the headers array are replaced
     * with id.toString().
     * 
     * 
     * @return the Array of column headers.
     */
    public String[] getColumnHeaders() {
        if (columnHeaders == null) {
            return null;
        }
        final String[] headers = new String[visibleColumns.size()];
        int i = 0;
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext(); i++) {
            headers[i] = getColumnHeader(it.next());
        }
        return headers;
    }

    /**
     * Sets the headers of the columns.
     * 
     * <p>
     * The headers match the property id:s given my the set visible column
     * headers. The table must be set in either
     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the
     * headers. In the defaults mode any nulls in the headers array are replaced
     * with id.toString() outputs when rendering.
     * 
     * 
     * @param columnHeaders
     *            the Array of column headers that match the
     *            {@link #getVisibleColumns()} method.
     */
    public void setColumnHeaders(String... columnHeaders) {

        if (columnHeaders.length != visibleColumns.size()) {
            throw new IllegalArgumentException(
                    "The length of the headers array must match the number of visible columns");
        }

        this.columnHeaders.clear();
        int i = 0;
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext() && i < columnHeaders.length; i++) {
            this.columnHeaders.put(it.next(), columnHeaders[i]);
        }

        markAsDirty();
    }

    /**
     * Gets the icons of the columns.
     * 
     * <p>
     * The icons in headers match the property id:s given my the set visible
     * column headers. The table must be set in either
     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the headers
     * with icons.
     * 
     * 
     * @return the Array of icons that match the {@link #getVisibleColumns()}.
     */
    public Resource[] getColumnIcons() {
        if (columnIcons == null) {
            return null;
        }
        final Resource[] icons = new Resource[visibleColumns.size()];
        int i = 0;
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext(); i++) {
            icons[i] = columnIcons.get(it.next());
        }

        return icons;
    }

    /**
     * Sets the icons of the columns.
     * 
     * <p>
     * The icons in headers match the property id:s given my the set visible
     * column headers. The table must be set in either
     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the headers
     * with icons.
     * 
     * 
     * @param columnIcons
     *            the Array of icons that match the {@link #getVisibleColumns()}
     *            .
     */
    public void setColumnIcons(Resource... columnIcons) {

        if (columnIcons.length != visibleColumns.size()) {
            throw new IllegalArgumentException(
                    "The length of the icons array must match the number of visible columns");
        }

        this.columnIcons.clear();
        int i = 0;
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext() && i < columnIcons.length; i++) {
            this.columnIcons.put(it.next(), columnIcons[i]);
        }

        markAsDirty();
    }

    /**
     * Gets the array of column alignments.
     * 
     * <p>
     * The items in the array must match the properties identified by
     * {@link #getVisibleColumns()}. The possible values for the alignments
     * include:
     * <ul>
     * <li>{@link Align#LEFT}: Left alignment</li>
     * <li>{@link Align#CENTER}: Centered</li>
     * <li>{@link Align#RIGHT}: Right alignment</li>
     * </ul>
     * The alignments default to {@link Align#LEFT}: any null values are
     * rendered as align lefts.
     * 
     * 
     * @return the Column alignments array.
     */
    public Align[] getColumnAlignments() {
        if (columnAlignments == null) {
            return null;
        }
        final Align[] alignments = new Align[visibleColumns.size()];
        int i = 0;
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext(); i++) {
            alignments[i] = getColumnAlignment(it.next());
        }

        return alignments;
    }

    /**
     * Sets the column alignments.
     * 
     * <p>
     * The amount of items in the array must match the amount of properties
     * identified by {@link #getVisibleColumns()}. The possible values for the
     * alignments include:
     * <ul>
     * <li>{@link Align#LEFT}: Left alignment</li>
     * <li>{@link Align#CENTER}: Centered</li>
     * <li>{@link Align#RIGHT}: Right alignment</li>
     * </ul>
     * The alignments default to {@link Align#LEFT}
     * 
     * 
     * @param columnAlignments
     *            the Column alignments array.
     */
    public void setColumnAlignments(Align... columnAlignments) {

        if (columnAlignments.length != visibleColumns.size()) {
            throw new IllegalArgumentException(
                    "The length of the alignments array must match the number of visible columns");
        }

        // Resets the alignments
        final HashMap<Object, Align> newCA = new HashMap<>();
        int i = 0;
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext() && i < columnAlignments.length; i++) {
            newCA.put(it.next(), columnAlignments[i]);
        }
        this.columnAlignments = newCA;

        // Assures the visual refresh. No need to reset the page buffer before
        // as the content has not changed, only the alignments.
        refreshRenderedCells();
    }

    /**
     * Sets columns width (in pixels). Theme may not necessary respect very
     * small or very big values. Setting width to -1 (default) means that theme
     * will make decision of width.
     * 
     * <p>
     * Column can either have a fixed width or expand ratio. The latter one set
     * is used. See @link {@link #setColumnExpandRatio(Object, float)}.
     * 
     * @param propertyId
     *            colunmns property id
     * @param width
     *            width to be reserved for colunmns content
     * @since 4.0.3
     */
    public void setColumnWidth(Object propertyId, int width) {
        if (propertyId == null) {
            // Since propertyId is null, this is the row header. Use the magic
            // id to store the width of the row header.
            propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
        }

        // Setting column width should remove any expand ratios as well
        columnExpandRatios.remove(propertyId);

        if (width < 0) {
            columnWidths.remove(propertyId);
        } else {
            columnWidths.put(propertyId, width);
        }
        markAsDirty();
    }

    /**
     * Sets the column expand ratio for given column.
     * <p>
     * Expand ratios can be defined to customize the way how excess space is
     * divided among columns. CustomTable can have excess space if it has its
     * width defined and there is horizontally more space than columns consume
     * naturally. Excess space is the space that is not used by columns with
     * explicit width (see {@link #setColumnWidth(Object, int)}) or with natural
     * width (no width nor expand ratio).
     * 
     * <p>
     * By default (without expand ratios) the excess space is divided
     * proportionally to columns natural widths.
     * 
     * <p>
     * Only expand ratios of visible columns are used in final calculations.
     * 
     * <p>
     * Column can either have a fixed width or expand ratio. The latter one set
     * is used.
     * 
     * <p>
     * A column with expand ratio is considered to be minimum width by default
     * (if no excess space exists). The minimum width is defined by terminal
     * implementation.
     * 
     * <p>
     * If terminal implementation supports re-sizable columns the column becomes
     * fixed width column if users resizes the column.
     * 
     * @param propertyId
     *            columns property id
     * @param expandRatio
     *            the expandRatio used to divide excess space for this column
     */
    public void setColumnExpandRatio(Object propertyId, float expandRatio) {
        if (propertyId == null) {
            // Since propertyId is null, this is the row header. Use the magic
            // id to store the width of the row header.
            propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
        }

        // Setting the column expand ratio should remove and defined column
        // width
        columnWidths.remove(propertyId);

        if (expandRatio < 0) {
            columnExpandRatios.remove(propertyId);
        } else {
            columnExpandRatios.put(propertyId, expandRatio);
        }

        requestRepaint();
    }

    /**
     * Gets the column expand ratio for a columnd. See
     * {@link #setColumnExpandRatio(Object, float)}
     * 
     * @param propertyId
     *            columns property id
     * @return the expandRatio used to divide excess space for this column
     */
    public float getColumnExpandRatio(Object propertyId) {
        final Float width = columnExpandRatios.get(propertyId);
        if (width == null) {
            return -1;
        }
        return width.floatValue();
    }

    /** Gets the pixel width of column.
	 *
	 * @param propertyId
	 *            the property id
	 * @return width of column or -1 when value not set
	 */
    public int getColumnWidth(Object propertyId) {
        if (propertyId == null) {
            // Since propertyId is null, this is the row header. Use the magic
            // id to retrieve the width of the row header.
            propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
        }
        final Integer width = columnWidths.get(propertyId);
        if (width == null) {
            return -1;
        }
        return width.intValue();
    }

    /**
     * Gets the page length.
     * 
     * <p>
     * Setting page length 0 disables paging.
     * 
     * 
     * @return the Length of one page.
     */
    public int getPageLength() {
        return pageLength;
    }

    /**
     * Sets the page length.
     * 
     * <p>
     * Setting page length 0 disables paging. The page length defaults to 15.
     * 
     * 
     * <p>
     * If CustomTable has width set ({@link #setColumnWidth(Object, int)} ) the client
     * side may update the page length automatically the correct value.
     * 
     * 
     * @param pageLength
     *            the length of one page.
     */
    public void setPageLength(int pageLength) {
        if (pageLength >= 0 && this.pageLength != pageLength) {
            this.pageLength = pageLength;
            // Assures the visual refresh
            refreshRowCache();
        }
    }

    /**
     * This method adjusts a possible caching mechanism of table implementation.
     * 
     * <p>
     * CustomTable component may fetch and render some rows outside visible
     * area. With complex tables (for example containing layouts and
     * components), the client side may become unresponsive. Setting the value
     * lower, UI will become more responsive. With higher values scrolling in
     * client will hit server less frequently.
     * 
     * <p>
     * The amount of cached rows will be cacheRate multiplied with pageLength (
     * {@link #setPageLength(int)} both below and above visible area..
     * 
     * @param cacheRate
     *            a value over 0 (fastest rendering time). Higher value will
     *            cache more rows on server (smoother scrolling). Default value
     *            is 2.
     */
    public void setCacheRate(double cacheRate) {
        if (cacheRate < 0) {
            throw new IllegalArgumentException(
                    "cacheRate cannot be less than zero");
        }
        if (this.cacheRate != cacheRate) {
            this.cacheRate = cacheRate;
            markAsDirty();
        }
    }

    /** Gets the cache rate.
	 *
	 * @return the current cache rate value
	 * @see #setCacheRate(double)
	 */
    public double getCacheRate() {
        return cacheRate;
    }

    /**
     * Getter for property currentPageFirstItem.
     * 
     * @return the Value of property currentPageFirstItem.
     */
    public Object getCurrentPageFirstItemId() {

        // Priorise index over id if indexes are supported
        if (items instanceof Container.Indexed) {
            final int index = getCurrentPageFirstItemIndex();
            Object id = null;
            if (index >= 0 && index < size()) {
                id = getIdByIndex(index);
            }
            if (id != null && !id.equals(currentPageFirstItemId)) {
                currentPageFirstItemId = id;
            }
        }

        // If there is no item id at all, use the first one
        if (currentPageFirstItemId == null) {
            currentPageFirstItemId = firstItemId();
        }

        return currentPageFirstItemId;
    }

    /**
     * Returns the item ID for the item represented by the index given. Assumes
     * that the current container implements {@link Container.Indexed}.
     * 
     * See {@link Container.Indexed#getIdByIndex(int)} for more information
     * about the exceptions that can be thrown.
     * 
     * @param index
     *            the index for which the item ID should be fetched
     * @return the item ID for the given index
     * 
     * @throws ClassCastException
     *             if container does not implement {@link Container.Indexed}
     * @throws IndexOutOfBoundsException
     *             thrown by {@link Container.Indexed#getIdByIndex(int)} if the
     *             index is invalid
     */
    protected Object getIdByIndex(int index) {
        return ((Container.Indexed) items).getIdByIndex(index);
    }

    /**
     * Setter for property currentPageFirstItemId.
     * 
     * @param currentPageFirstItemId
     *            the New value of property currentPageFirstItemId.
     */
    public void setCurrentPageFirstItemId(Object currentPageFirstItemId) {

        // Gets the corresponding index
        int index = -1;
        if (items instanceof Container.Indexed) {
            index = indexOfId(currentPageFirstItemId);
        } else {
            // If the table item container does not have index, we have to
            // calculates the index by hand
            Object id = firstItemId();
            while (id != null && !id.equals(currentPageFirstItemId)) {
                index++;
                id = nextItemId(id);
            }
            if (id == null) {
                index = -1;
            }
        }

        // If the search for item index was successful
        if (index >= 0) {
            /*
             * The table is not capable of displaying an item in the container
             * as the first if there are not enough items following the selected
             * item so the whole table (pagelength) is filled.
             */
            int maxIndex = size() - pageLength;
            if (maxIndex < 0) {
                maxIndex = 0;
            }

            if (index > maxIndex) {
                // Note that we pass index, not maxIndex, letting
                // setCurrentPageFirstItemIndex handle the situation.
                setCurrentPageFirstItemIndex(index);
                return;
            }

            this.currentPageFirstItemId = currentPageFirstItemId;
            currentPageFirstItemIndex = index;
        }

        // Assures the visual refresh
        refreshRowCache();

    }

    /** Index of id.
	 *
	 * @param itemId
	 *            the item id
	 * @return the int
	 */
    protected int indexOfId(Object itemId) {
        return ((Container.Indexed) items).indexOfId(itemId);
    }

    /**
     * Gets the icon Resource for the specified column.
     * 
     * @param propertyId
     *            the propertyId indentifying the column.
     * @return the icon for the specified column; null if the column has no icon
     *         set, or if the column is not visible.
     */
    public Resource getColumnIcon(Object propertyId) {
        return columnIcons.get(propertyId);
    }

    /**
     * Sets the icon Resource for the specified column.
     * <p>
     * Throws IllegalArgumentException if the specified column is not visible.
     * 
     * 
     * @param propertyId
     *            the propertyId identifying the column.
     * @param icon
     *            the icon Resource to set.
     */
    public void setColumnIcon(Object propertyId, Resource icon) {

        if (icon == null) {
            columnIcons.remove(propertyId);
        } else {
            columnIcons.put(propertyId, icon);
        }

        markAsDirty();
    }

    /**
     * Gets the header for the specified column.
     * 
     * @param propertyId
     *            the propertyId identifying the column.
     * @return the header for the specified column if it has one.
     */
    public String getColumnHeader(Object propertyId) {
        if (getColumnHeaderMode() == ColumnHeaderMode.HIDDEN) {
            return null;
        }

        String header = columnHeaders.get(propertyId);
        if ((header == null && getColumnHeaderMode() == ColumnHeaderMode.EXPLICIT_DEFAULTS_ID)
                || getColumnHeaderMode() == ColumnHeaderMode.ID) {
            header = propertyId.toString();
        }

        return header;
    }

    /** Sets the column header for the specified column;.
	 *
	 * @param propertyId
	 *            the propertyId identifying the column.
	 * @param header
	 *            the header to set.
	 */
    public void setColumnHeader(Object propertyId, String header) {

        if (header == null) {
            columnHeaders.remove(propertyId);
        } else {
            columnHeaders.put(propertyId, header);
        }

        markAsDirty();
    }

    /**
     * Gets the specified column's alignment.
     * 
     * @param propertyId
     *            the propertyID identifying the column.
     * @return the specified column's alignment if it as one; {@link Align#LEFT}
     *         otherwise.
     */
    public Align getColumnAlignment(Object propertyId) {
        final Align a = columnAlignments.get(propertyId);
        return a == null ? Align.LEFT : a;
    }

    /**
     * Sets the specified column's alignment.
     * 
     * <p>
     * Throws IllegalArgumentException if the alignment is not one of the
     * following: {@link Align#LEFT}, {@link Align#CENTER} or
     * {@link Align#RIGHT}
     * 
     * 
     * @param propertyId
     *            the propertyID identifying the column.
     * @param alignment
     *            the desired alignment.
     */
    public void setColumnAlignment(Object propertyId, Align alignment) {
        if (alignment == null || alignment == Align.LEFT) {
            columnAlignments.remove(propertyId);
        } else {
            columnAlignments.put(propertyId, alignment);
        }

        // Assures the visual refresh. No need to reset the page buffer before
        // as the content has not changed, only the alignments.
        refreshRenderedCells();
    }

    /**
     * Checks if the specified column is collapsed.
     * 
     * @param propertyId
     *            the propertyID identifying the column.
     * @return true if the column is collapsed; false otherwise;
     */
    public boolean isColumnCollapsed(Object propertyId) {
        return collapsedColumns != null
                && collapsedColumns.contains(propertyId);
    }

    /**
     * Sets whether the specified column is collapsed or not.
     * 
     * 
     * @param propertyId
     *            the propertyID identifying the column.
     * @param collapsed
     *            the desired collapsedness.
     * @throws IllegalStateException
     *             if column collapsing is not allowed
     */
    public void setColumnCollapsed(Object propertyId, boolean collapsed)
            throws IllegalStateException {
        if (!isColumnCollapsingAllowed()) {
            throw new IllegalStateException("Column collapsing not allowed!");
        }
        if (collapsed && noncollapsibleColumns.contains(propertyId)) {
            throw new IllegalStateException("The column is noncollapsible!");
        }

        if (collapsed) {
            collapsedColumns.add(propertyId);
        } else {
            collapsedColumns.remove(propertyId);
        }

        // Assures the visual refresh
        refreshRowCache();
    }

    /**
     * Checks if column collapsing is allowed.
     * 
     * @return true if columns can be collapsed; false otherwise.
     */
    public boolean isColumnCollapsingAllowed() {
        return columnCollapsingAllowed;
    }

    /**
     * Sets whether column collapsing is allowed or not.
     * 
     * @param collapsingAllowed
     *            specifies whether column collapsing is allowed.
     */
    public void setColumnCollapsingAllowed(boolean collapsingAllowed) {
        columnCollapsingAllowed = collapsingAllowed;

        if (!collapsingAllowed) {
            collapsedColumns.clear();
        }

        // Assures the visual refresh. No need to reset the page buffer before
        // as the content has not changed, only the alignments.
        refreshRenderedCells();
    }

    /**
     * Sets whether the given column is collapsible. Note that collapsible
     * columns can only be actually collapsed (via UI or with
     * {@link #setColumnCollapsed(Object, boolean) setColumnCollapsed()}) if
     * {@link #isColumnCollapsingAllowed()} is true. By default all columns are
     * collapsible.
     * 
     * @param propertyId
     *            the propertyID identifying the column.
     * @param collapsible
     *            true if the column should be collapsible, false otherwise.
     */
    public void setColumnCollapsible(Object propertyId, boolean collapsible) {
        if (collapsible) {
            noncollapsibleColumns.remove(propertyId);
        } else {
            noncollapsibleColumns.add(propertyId);
            collapsedColumns.remove(propertyId);
        }
        refreshRowCache();
    }

    /** Checks if the given column is collapsible. Note that even if this
	 * method returns <code>true</code>, the column can only be actually
	 * collapsed (via UI or with {@link #setColumnCollapsed(Object, boolean)
	 * setColumnCollapsed()}) if {@link #isColumnCollapsingAllowed()} is also
	 * true.
	 *
	 * @param propertyId
	 *            the property id
	 * @return true if the column can be collapsed; false otherwise.
	 */
    public boolean isColumnCollapsible(Object propertyId) {
        return !noncollapsibleColumns.contains(propertyId);
    }

    /**
     * Checks if column reordering is allowed.
     * 
     * @return true if columns can be reordered; false otherwise.
     */
    public boolean isColumnReorderingAllowed() {
        return columnReorderingAllowed;
    }

    /**
     * Sets whether column reordering is allowed or not.
     * 
     * @param columnReorderingAllowed
     *            specifies whether column reordering is allowed.
     */
    public void setColumnReorderingAllowed(boolean columnReorderingAllowed) {
        if (columnReorderingAllowed != this.columnReorderingAllowed) {
            this.columnReorderingAllowed = columnReorderingAllowed;
            markAsDirty();
        }
    }

    /** Sets the column order.
	 *
	 * @param columnOrder
	 *            the new column order
	 */
    /*
     * Arranges visible columns according to given columnOrder. Silently ignores
     * colimnId:s that are not visible columns, and keeps the internal order of
     * visible columns left out of the ordering (trailing). Silently does
     * nothing if columnReordering is not allowed.
     */
    private void setColumnOrder(Object[] columnOrder) {
        if (columnOrder == null || !isColumnReorderingAllowed()) {
            return;
        }
        final LinkedList<Object> newOrder = new LinkedList<>();
        for (int i = 0; i < columnOrder.length; i++) {
            if (columnOrder[i] != null
                    && visibleColumns.contains(columnOrder[i])) {
                visibleColumns.remove(columnOrder[i]);
                newOrder.add(columnOrder[i]);
            }
        }
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext();) {
            final Object columnId = it.next();
            if (!newOrder.contains(columnId)) {
                newOrder.add(columnId);
            }
        }
        visibleColumns = newOrder;

        // Assure visual refresh
        refreshRowCache();
    }

    /**
     * Getter for property currentPageFirstItem.
     * 
     * @return the Value of property currentPageFirstItem.
     */
    public int getCurrentPageFirstItemIndex() {
        return currentPageFirstItemIndex;
    }

    /** Sets the current page first item index.
	 *
	 * @param newIndex
	 *            the new index
	 * @param needsPageBufferReset
	 *            the needs page buffer reset
	 */
    void setCurrentPageFirstItemIndex(int newIndex, boolean needsPageBufferReset) {

        if (newIndex < 0) {
            newIndex = 0;
        }

        /*
         * minimize Container.size() calls which may be expensive. For example
         * it may cause sql query.
         */
        final int size = size();

        /*
         * The table is not capable of displaying an item in the container as
         * the first if there are not enough items following the selected item
         * so the whole table (pagelength) is filled.
         */
        int maxIndex = size - pageLength;
        if (maxIndex < 0) {
            maxIndex = 0;
        }

        /*
         * If the new index is on the last page we set the index to be the first
         * item on that last page and make a note of the real index for the
         * client side to be able to move the scroll position to the correct
         * position.
         */
        int indexOnLastPage = -1;
        if (newIndex > maxIndex) {
            indexOnLastPage = newIndex;
            newIndex = maxIndex;
        }

        // Refresh first item id
        if (items instanceof Container.Indexed) {
            try {
                currentPageFirstItemId = getIdByIndex(newIndex);
            } catch (final IndexOutOfBoundsException e) {
                currentPageFirstItemId = null;
            }
            currentPageFirstItemIndex = newIndex;

            if (needsPageBufferReset) {
                /*
                 * The flag currentPageFirstItemIndexOnLastPage denotes a user
                 * set scrolling position on the last page via
                 * setCurrentPageFirstItemIndex() and shouldn't be changed by
                 * the table component internally changing the firstvisible item
                 * on lazy row fetching. Doing so would make the scrolling
                 * position not be updated correctly when the lazy rows are
                 * finally rendered.
                 */

                boolean isLastRowPossiblyPartiallyVisible = true;
                if (indexOnLastPage != -1) {
                    /*
                     * If the requested row was greater than maxIndex, the last
                     * row should be fully visible (See
                     * TestCurrentPageFirstItem).
                     */
                    isLastRowPossiblyPartiallyVisible = false;
                }

                int extraRows = isLastRowPossiblyPartiallyVisible ? 0 : 1;
                currentPageFirstItemIndexOnLastPage = currentPageFirstItemIndex
                        + extraRows;
            } else {
                currentPageFirstItemIndexOnLastPage = -1;
            }

        } else {

            // For containers not supporting indexes, we must iterate the
            // container forwards / backwards
            // next available item forward or backward

            currentPageFirstItemId = firstItemId();

            // Go forwards in the middle of the list (respect borders)
            while (currentPageFirstItemIndex < newIndex
                    && !isLastId(currentPageFirstItemId)) {
                currentPageFirstItemIndex++;
                currentPageFirstItemId = nextItemId(currentPageFirstItemId);
            }

            // If we did hit the border
            if (isLastId(currentPageFirstItemId)) {
                currentPageFirstItemIndex = size - 1;
            }

            // Go backwards in the middle of the list (respect borders)
            while (currentPageFirstItemIndex > newIndex
                    && !isFirstId(currentPageFirstItemId)) {
                currentPageFirstItemIndex--;
                currentPageFirstItemId = prevItemId(currentPageFirstItemId);
            }

            // If we did hit the border
            if (isFirstId(currentPageFirstItemId)) {
                currentPageFirstItemIndex = 0;
            }

            // Go forwards once more
            while (currentPageFirstItemIndex < newIndex
                    && !isLastId(currentPageFirstItemId)) {
                currentPageFirstItemIndex++;
                currentPageFirstItemId = nextItemId(currentPageFirstItemId);
            }

            // If for some reason we do hit border again, override
            // the user index request
            if (isLastId(currentPageFirstItemId)) {
                newIndex = currentPageFirstItemIndex = size - 1;
            }
        }
        if (needsPageBufferReset) {
            // Assures the visual refresh
            refreshRowCache();
        }
    }

    /**
     * Setter for property currentPageFirstItem.
     * 
     * @param newIndex
     *            the New value of property currentPageFirstItem.
     */
    public void setCurrentPageFirstItemIndex(int newIndex) {
        setCurrentPageFirstItemIndex(newIndex, true);
    }

    /**
     * Getter for property selectable.
     * 
     * <p>
     * The table is not selectable by default.
     * 
     * 
     * @return the Value of property selectable.
     */
    public boolean isSelectable() {
        return selectable;
    }

    /**
     * Setter for property selectable.
     * 
     * <p>
     * The table is not selectable by default.
     * 
     * 
     * @param selectable
     *            the New value of property selectable.
     */
    public void setSelectable(boolean selectable) {
        if (this.selectable != selectable) {
            this.selectable = selectable;
            markAsDirty();
        }
    }

    /**
     * Getter for property columnHeaderMode.
     * 
     * @return the Value of property columnHeaderMode.
     */
    public ColumnHeaderMode getColumnHeaderMode() {
        return columnHeaderMode;
    }

    /**
     * Setter for property columnHeaderMode.
     * 
     * @param columnHeaderMode
     *            the New value of property columnHeaderMode.
     */
    public void setColumnHeaderMode(ColumnHeaderMode columnHeaderMode) {
        if (columnHeaderMode == null) {
            throw new IllegalArgumentException(
                    "Column header mode can not be null");
        }
        if (columnHeaderMode != this.columnHeaderMode) {
            this.columnHeaderMode = columnHeaderMode;
            markAsDirty();
        }

    }

    /**
     * Refreshes the rows in the internal cache. Only if
     * {@link #resetPageBuffer()} is called before this then all values are
     * guaranteed to be recreated.
     */
    protected void refreshRenderedCells() {
        if (!isAttached()) {
            return;
        }

        if (!isContentRefreshesEnabled) {
            return;
        }

        // Collects the basic facts about the table page
        final int pagelen = getPageLength();
        int rows, totalRows;
        rows = totalRows = size();
        int firstIndex = Math
                .min(getCurrentPageFirstItemIndex(), totalRows - 1);
        if (rows > 0 && firstIndex >= 0) {
            rows -= firstIndex;
        }
        if (pagelen > 0 && pagelen < rows) {
            rows = pagelen;
        }

        // If "to be painted next" variables are set, use them
        if (lastToBeRenderedInClient - firstToBeRenderedInClient > 0) {
            rows = lastToBeRenderedInClient - firstToBeRenderedInClient + 1;
        }
        if (firstToBeRenderedInClient >= 0) {
            if (firstToBeRenderedInClient < totalRows) {
                firstIndex = firstToBeRenderedInClient;
            } else {
                firstIndex = totalRows - 1;
            }
        } else {
            // initial load

            // #8805 send one extra row in the beginning in case a partial
            // row is shown on the UI
            if (firstIndex > 0) {
                firstIndex = firstIndex - 1;
                rows = rows + 1;
            }
            firstToBeRenderedInClient = firstIndex;
        }
        if (totalRows > 0) {
            if (rows + firstIndex > totalRows) {
                rows = totalRows - firstIndex;
            }
        } else {
            rows = 0;
        }

        // Saves the results to internal buffer
        pageBuffer = getVisibleCellsNoCache(firstIndex, rows, true);

        if (rows > 0) {
            pageBufferFirstIndex = firstIndex;
        }
        if (getPageLength() != 0) {
            removeUnnecessaryRows();
        }

        setRowCacheInvalidated(true);
        markAsDirty();
        maybeThrowCacheUpdateExceptions();

    }

    /** Maybe throw cache update exceptions.
	 */
    private void maybeThrowCacheUpdateExceptions() {
        if (!exceptionsDuringCachePopulation.isEmpty()) {
            Throwable[] causes = new Throwable[exceptionsDuringCachePopulation
                    .size()];
            exceptionsDuringCachePopulation.toArray(causes);

            exceptionsDuringCachePopulation.clear();
            throw new CacheUpdateException(this,
                    "Error during CustomTable cache update.", causes);
        }

    }

    /**
     * Exception thrown when one or more exceptions occurred during updating of
     * the CustomTable cache.
     * <p>
     * Contains all exceptions which occurred during the cache update. The first
     * occurred exception is set as the cause of this exception. All occurred
     * exceptions can be accessed using {@link #getCauses()}.
     * 
     * 
     */
    public static class CacheUpdateException extends RuntimeException {
        
        /**
		 * 
		 */
		private static final long serialVersionUID = -1890917091988174455L;

		/** The causes. */
        private Throwable[] causes;
        
        /** The table. */
        private CustomTable table;

        /** Instantiates a new cache update exception.
		 *
		 * @param table
		 *            the table
		 * @param message
		 *            the message
		 * @param causes
		 *            the causes
		 */
        public CacheUpdateException(CustomTable table, String message,
                Throwable[] causes) {
            super(maybeSupplementMessage(message, causes.length), causes[0]);
            this.table = table;
            this.causes = causes;
        }

        /** Maybe supplement message.
		 *
		 * @param message
		 *            the message
		 * @param causeCount
		 *            the cause count
		 * @return the string
		 */
        private static String maybeSupplementMessage(String message,
                int causeCount) {
            if (causeCount > 1) {
                return message + " Additional causes not shown.";
            }
            return message;
        }

        /** Returns the cause(s) for this exception.
		 *
		 * @return the exception(s) which caused this exception
		 */
        public Throwable[] getCauses() {
            return causes;
        }

        /** Gets the table.
		 *
		 * @return the table
		 */
        public CustomTable getTable() {
            return table;
        }

    }

    /**
     * Removes rows that fall outside the required cache.
     */
    private void removeUnnecessaryRows() {
        int minPageBufferIndex = getMinPageBufferIndex();
        int maxPageBufferIndex = getMaxPageBufferIndex();

        int maxBufferSize = maxPageBufferIndex - minPageBufferIndex + 1;

        /*
         * Number of rows that were previously cached. This is not necessarily
         * the same as pageLength if we do not have enough rows in the
         * container.
         */
        int currentlyCachedRowCount = pageBuffer[CELL_ITEMID].length;

        if (currentlyCachedRowCount <= maxBufferSize) {
            // removal unnecessary
            return;
        }

        /* Figure out which rows to get rid of. */
        int firstCacheRowToRemoveInPageBuffer = -1;
        if (minPageBufferIndex > pageBufferFirstIndex) {
            firstCacheRowToRemoveInPageBuffer = pageBufferFirstIndex;
        } else if (maxPageBufferIndex < pageBufferFirstIndex
                + currentlyCachedRowCount) {
            firstCacheRowToRemoveInPageBuffer = maxPageBufferIndex + 1;
        }

        if (firstCacheRowToRemoveInPageBuffer - pageBufferFirstIndex < currentlyCachedRowCount) {
            /*
             * Unregister all components that fall beyond the cache limits after
             * inserting the new rows.
             */
            unregisterComponentsAndPropertiesInRows(
                    firstCacheRowToRemoveInPageBuffer, currentlyCachedRowCount
                            - firstCacheRowToRemoveInPageBuffer);
        }
    }

    /**
     * Requests that the CustomTable should be repainted as soon as possible.
     * 
     * Note that a {@code CustomTable} does not necessarily repaint its contents
     * when this method has been called. See {@link #refreshRowCache()} for
     * forcing an update of the contents.
     * 
     * @deprecated As of 7.0, use {@link #markAsDirty()} instead
     */

    @Deprecated
    @Override
    public void requestRepaint() {
        markAsDirty();
    }

    /**
     * Requests that the CustomTable should be repainted as soon as possible.
     * 
     * Note that a {@code CustomTable} does not necessarily repaint its contents
     * when this method has been called. See {@link #refreshRowCache()} for
     * forcing an update of the contents.
     */

    @Override
    public void markAsDirty() {
        // Overridden only for javadoc
        super.markAsDirty();
    }

    /* (non-Javadoc)
     * @see com.vaadin.server.AbstractClientConnector#markAsDirtyRecursive()
     */
    @Override
    public void markAsDirtyRecursive() {
        super.markAsDirtyRecursive();

        // Avoid sending a partial repaint (#8714)
        refreshRowCache();
    }

    /** Removes the rows from cache and fill bottom.
	 *
	 * @param firstIndex
	 *            the first index
	 * @param rows
	 *            the rows
	 */
    private void removeRowsFromCacheAndFillBottom(int firstIndex, int rows) {
        int totalCachedRows = pageBuffer[CELL_ITEMID].length;
        int totalRows = size();
        int firstIndexInPageBuffer = firstIndex - pageBufferFirstIndex;

        /*
         * firstIndexInPageBuffer is the first row to be removed. "rows" rows
         * after that should be removed. If the page buffer does not contain
         * that many rows, we only remove the rows that actually are in the page
         * buffer.
         */
        if (firstIndexInPageBuffer + rows > totalCachedRows) {
            rows = totalCachedRows - firstIndexInPageBuffer;
        }

        /*
         * Unregister components that will no longer be in the page buffer to
         * make sure that no components leak.
         */
        unregisterComponentsAndPropertiesInRows(firstIndex, rows);

        /*
         * The number of rows that should be in the cache after this operation
         * is done (pageBuffer currently contains the expanded items).
         */
        int newCachedRowCount = totalCachedRows;
        if (newCachedRowCount + pageBufferFirstIndex > totalRows) {
            newCachedRowCount = totalRows - pageBufferFirstIndex;
        }

        /*
         * The index at which we should render the first row that does not come
         * from the previous page buffer.
         */
        int firstAppendedRowInPageBuffer = totalCachedRows - rows;
        int firstAppendedRow = firstAppendedRowInPageBuffer
                + pageBufferFirstIndex;

        /*
         * Calculate the maximum number of new rows that we can add to the page
         * buffer. Less than the rows we removed if the container does not
         * contain that many items afterwards.
         */
        int maxRowsToRender = (totalRows - firstAppendedRow);
        int rowsToAdd = rows;
        if (rowsToAdd > maxRowsToRender) {
            rowsToAdd = maxRowsToRender;
        }

        Object[][] cells = null;
        if (rowsToAdd > 0) {
            cells = getVisibleCellsNoCache(firstAppendedRow, rowsToAdd, false);
        }
        /*
         * Create the new cache buffer by copying the first rows from the old
         * buffer, moving the following rows upwards and appending more rows if
         * applicable.
         */
        Object[][] newPageBuffer = new Object[pageBuffer.length][newCachedRowCount];

        for (int i = 0; i < pageBuffer.length; i++) {
            for (int row = 0; row < firstIndexInPageBuffer; row++) {
                // Copy the first rows
                newPageBuffer[i][row] = pageBuffer[i][row];
            }
            for (int row = firstIndexInPageBuffer; row < firstAppendedRowInPageBuffer; row++) {
                // Move the rows that were after the expanded rows
                newPageBuffer[i][row] = pageBuffer[i][row + rows];
            }
            for (int row = firstAppendedRowInPageBuffer; row < newCachedRowCount; row++) {
                // Add the newly rendered rows. Only used if rowsToAdd > 0
                // (cells != null)
                newPageBuffer[i][row] = cells[i][row
                        - firstAppendedRowInPageBuffer];
            }
        }
        pageBuffer = newPageBuffer;
    }

    /** Gets the visible cells update cache rows.
	 *
	 * @param firstIndex
	 *            the first index
	 * @param rows
	 *            the rows
	 * @return the visible cells update cache rows
	 */
    private Object[][] getVisibleCellsUpdateCacheRows(int firstIndex, int rows) {
        Object[][] cells = getVisibleCellsNoCache(firstIndex, rows, false);
        int cacheIx = firstIndex - pageBufferFirstIndex;
        // update the new rows in the cache.
        int totalCachedRows = pageBuffer[CELL_ITEMID].length;
        int end = Math.min(cacheIx + rows, totalCachedRows);
        for (int ix = cacheIx; ix < end; ix++) {
            for (int i = 0; i < pageBuffer.length; i++) {
                pageBuffer[i][ix] = cells[i][ix - cacheIx];
            }
        }
        return cells;
    }

    /** Gets the visible cells insert into cache.
	 *
	 * @param firstIndex
	 *            The position where new rows should be inserted
	 * @param rows
	 *            The maximum number of rows that should be inserted at position
	 *            firstIndex. Less rows will be inserted if the page buffer is
	 *            too small.
	 * @return the visible cells insert into cache
	 */
    private Object[][] getVisibleCellsInsertIntoCache(int firstIndex, int rows) {
        getLogger()
                .log(Level.FINEST,
                        "Insert {0} rows at index {1} to existing page buffer requested",
                        new Object[] { rows, firstIndex });

        int minPageBufferIndex = getMinPageBufferIndex();
        int maxPageBufferIndex = getMaxPageBufferIndex();

        int maxBufferSize = maxPageBufferIndex - minPageBufferIndex + 1;

        if (getPageLength() == 0) {
            // If pageLength == 0 then all rows should be rendered
            maxBufferSize = pageBuffer[CELL_ITEMID].length + rows;
        }
        /*
         * Number of rows that were previously cached. This is not necessarily
         * the same as maxBufferSize.
         */
        int currentlyCachedRowCount = pageBuffer[CELL_ITEMID].length;

        /* If rows > size available in page buffer */
        if (firstIndex + rows - 1 > maxPageBufferIndex) {
            rows = maxPageBufferIndex - firstIndex + 1;
        }

        /*
         * "rows" rows will be inserted at firstIndex. Find out how many old
         * rows fall outside the new buffer so we can unregister components in
         * the cache.
         */

        /*
         * if there are rows before the new pageBuffer limits they must be
         * removed
         */
        int lastCacheRowToRemove = minPageBufferIndex - 1;
        int rowsFromBeginning = lastCacheRowToRemove - pageBufferFirstIndex + 1;
        if (lastCacheRowToRemove >= pageBufferFirstIndex) {
            unregisterComponentsAndPropertiesInRows(pageBufferFirstIndex,
                    rowsFromBeginning);
        } else {
            rowsFromBeginning = 0;
        }

        /*
         * the rows that fall outside of the new pageBuffer limits after the new
         * rows are inserted must also be removed
         */
        int firstCacheRowToRemove = firstIndex;
        /*
         * IF there is space remaining in the buffer after the rows have been
         * inserted, we can keep more rows.
         */
        int numberOfOldRowsAfterInsertedRows = Math.min(pageBufferFirstIndex
                + currentlyCachedRowCount + rows, maxPageBufferIndex + 1)
                - (firstIndex + rows - 1);
        if (numberOfOldRowsAfterInsertedRows > 0) {
            firstCacheRowToRemove += numberOfOldRowsAfterInsertedRows;
        }
        int rowsFromAfter = currentlyCachedRowCount
                - (firstCacheRowToRemove - pageBufferFirstIndex);

        if (rowsFromAfter > 0) {
            /*
             * Unregister all components that fall beyond the cache limits after
             * inserting the new rows.
             */
            unregisterComponentsAndPropertiesInRows(firstCacheRowToRemove,
                    rowsFromAfter);
        }

        // Calculate the new cache size
        int newCachedRowCount = maxBufferSize;
        if (pageBufferFirstIndex + currentlyCachedRowCount + rows - 1 < maxPageBufferIndex) {
            // there aren't enough rows to fill the whole potential -> use what
            // there is
            newCachedRowCount -= maxPageBufferIndex
                    - (pageBufferFirstIndex + currentlyCachedRowCount + rows - 1);
        } else if (minPageBufferIndex < pageBufferFirstIndex) {
            newCachedRowCount -= pageBufferFirstIndex - minPageBufferIndex;
        }
        /* calculate the internal location of the new rows within the new cache */
        int firstIndexInNewPageBuffer = firstIndex - pageBufferFirstIndex
                - rowsFromBeginning;

        /* Paint the new rows into a separate buffer */
        Object[][] cells = getVisibleCellsNoCache(firstIndex, rows, false);

        /*
         * Create the new cache buffer and fill it with the data from the old
         * buffer as well as the inserted rows.
         */
        Object[][] newPageBuffer = new Object[pageBuffer.length][newCachedRowCount];

        for (int i = 0; i < pageBuffer.length; i++) {
            for (int row = 0; row < firstIndexInNewPageBuffer; row++) {
                // Copy the first rows
                newPageBuffer[i][row] = pageBuffer[i][rowsFromBeginning + row];
            }
            for (int row = firstIndexInNewPageBuffer; row < firstIndexInNewPageBuffer
                    + rows; row++) {
                // Copy the newly created rows
                newPageBuffer[i][row] = cells[i][row
                        - firstIndexInNewPageBuffer];
            }
            for (int row = firstIndexInNewPageBuffer + rows; row < newCachedRowCount; row++) {
                // Move the old rows down below the newly inserted rows
                newPageBuffer[i][row] = pageBuffer[i][rowsFromBeginning + row
                        - rows];
            }
        }
        pageBuffer = newPageBuffer;
        pageBufferFirstIndex = Math.max(pageBufferFirstIndex
                + rowsFromBeginning, minPageBufferIndex);
        if (getLogger().isLoggable(Level.FINEST)) {
            getLogger().log(
                    Level.FINEST,
                    "Page Buffer now contains {0} rows ({1}-{2})",
                    new Object[] {
                            pageBuffer[CELL_ITEMID].length,
                            pageBufferFirstIndex,
                            (pageBufferFirstIndex
                                    + pageBuffer[CELL_ITEMID].length - 1) });
        }
        return cells;
    }

    /** Gets the max page buffer index.
	 *
	 * @return the max page buffer index
	 */
    private int getMaxPageBufferIndex() {
        int total = size();
        if (getPageLength() == 0) {
            // everything is shown at once, no caching
            return total - 1;
        }
        // Page buffer must not become larger than pageLength*cacheRate after
        // the current page
        int maxPageBufferIndex = getCurrentPageFirstItemIndex()
                + (int) (getPageLength() * (1 + getCacheRate()));
        if (shouldHideNullSelectionItem()) {
            --total;
        }
        if (maxPageBufferIndex >= total) {
            maxPageBufferIndex = total - 1;
        }
        return maxPageBufferIndex;
    }

    /** Gets the min page buffer index.
	 *
	 * @return the min page buffer index
	 */
    private int getMinPageBufferIndex() {
        if (getPageLength() == 0) {
            // everything is shown at once, no caching
            return 0;
        }
        // Page buffer must not become larger than pageLength*cacheRate before
        // the current page
        int minPageBufferIndex = getCurrentPageFirstItemIndex()
                - (int) (getPageLength() * getCacheRate());
        if (minPageBufferIndex < 0) {
            minPageBufferIndex = 0;
        }
        return minPageBufferIndex;
    }

    /** Render rows with index "firstIndex" to "firstIndex+rows-1" to a new
	 * buffer.
	 * 
	 * Reuses values from the current page buffer if the rows are found there.
	 *
	 * @param firstIndex
	 *            the first index
	 * @param rows
	 *            the rows
	 * @param replaceListeners
	 *            the replace listeners
	 * @return the visible cells no cache
	 */
    private Object[][] getVisibleCellsNoCache(int firstIndex, int rows,
            boolean replaceListeners) {
        if (getLogger().isLoggable(Level.FINEST)) {
            getLogger().log(Level.FINEST,
                    "Render visible cells for rows {0}-{1}",
                    new Object[] { firstIndex, (firstIndex + rows - 1) });
        }
        final Object[] colids = getVisibleColumns();
        final int cols = colids.length;

        HashSet<Property<?>> oldListenedProperties = listenedProperties;
        HashSet<Component> oldVisibleComponents = visibleComponents;

        if (replaceListeners) {
            // initialize the listener collections, this should only be done if
            // the entire cache is refreshed (through refreshRenderedCells)
            listenedProperties = new HashSet<>();
            visibleComponents = new HashSet<>();
        }

        Object[][] cells = new Object[cols + CELL_FIRSTCOL][rows];
        if (rows == 0) {
            unregisterPropertiesAndComponents(oldListenedProperties,
                    oldVisibleComponents);
            return cells;
        }

        final RowHeaderMode headmode = getRowHeaderMode();
        final boolean[] iscomponent = new boolean[cols];
        for (int i = 0; i < cols; i++) {
            iscomponent[i] = columnGenerators.containsKey(colids[i])
                    || Component.class.isAssignableFrom(getType(colids[i]));
        }
        int firstIndexNotInCache;
        if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) {
            firstIndexNotInCache = pageBufferFirstIndex
                    + pageBuffer[CELL_ITEMID].length;
        } else {
            firstIndexNotInCache = -1;
        }

        // Creates the page contents
        int filledRows = 0;
        if (items instanceof Container.Indexed) {
            // more efficient implementation for containers supporting access by
            // index

            List<?> itemIds = getItemIds(firstIndex, rows);
            for (int i = 0; i < rows && i < itemIds.size(); i++) {
                Object id = itemIds.get(i);
                // Start by parsing the values, id should already be set
                parseItemIdToCells(cells, id, i, firstIndex, headmode, cols,
                        colids, firstIndexNotInCache, iscomponent,
                        oldListenedProperties);

                filledRows++;
            }
        } else {
            // slow back-up implementation for cases where the container does
            // not support access by index

            // Gets the first item id
            Object id = firstItemId();
            for (int i = 0; i < firstIndex; i++) {
                id = nextItemId(id);
            }
            for (int i = 0; i < rows && id != null; i++) {
                // Start by parsing the values, id should already be set
                parseItemIdToCells(cells, id, i, firstIndex, headmode, cols,
                        colids, firstIndexNotInCache, iscomponent,
                        oldListenedProperties);

                // Gets the next item id for non indexed container
                id = nextItemId(id);

                filledRows++;
            }
        }

        // Assures that all the rows of the cell-buffer are valid
        if (filledRows != cells[0].length) {
            final Object[][] temp = new Object[cells.length][filledRows];
            for (int i = 0; i < cells.length; i++) {
                for (int j = 0; j < filledRows; j++) {
                    temp[i][j] = cells[i][j];
                }
            }
            cells = temp;
        }

        unregisterPropertiesAndComponents(oldListenedProperties,
                oldVisibleComponents);

        return cells;
    }

    /** Gets the item ids.
	 *
	 * @param firstIndex
	 *            the first index
	 * @param rows
	 *            the rows
	 * @return the item ids
	 */
    protected List<Object> getItemIds(int firstIndex, int rows) {
        return (List<Object>) ((Container.Indexed) items).getItemIds(
                firstIndex, rows);
    }

    /** Update a cache array for a row, register any relevant listeners etc.
	 * 
	 * This is an internal method extracted from
	 * {@link #getVisibleCellsNoCache(int, int, boolean)} and should be removed
	 * when the CustomTable is rewritten.
	 *
	 * @param cells
	 *            the cells
	 * @param id
	 *            the id
	 * @param i
	 *            the i
	 * @param firstIndex
	 *            the first index
	 * @param headmode
	 *            the headmode
	 * @param cols
	 *            the cols
	 * @param colids
	 *            the colids
	 * @param firstIndexNotInCache
	 *            the first index not in cache
	 * @param iscomponent
	 *            the iscomponent
	 * @param oldListenedProperties
	 *            the old listened properties
	 */
    private void parseItemIdToCells(Object[][] cells, Object id, int i,
            int firstIndex, RowHeaderMode headmode, int cols, Object[] colids,
            int firstIndexNotInCache, boolean[] iscomponent,
            HashSet<Property<?>> oldListenedProperties) {

        cells[CELL_ITEMID][i] = id;
        cells[CELL_KEY][i] = itemIdMapper.key(id);
        if (headmode != ROW_HEADER_MODE_HIDDEN) {
            switch (headmode) {
            case INDEX:
                cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1);
                break;
            default:
                try {
                    cells[CELL_HEADER][i] = getItemCaption(id);
                } catch (Exception e) {
                    exceptionsDuringCachePopulation.add(e);
                    cells[CELL_HEADER][i] = "";
                }
            }
            try {
                cells[CELL_ICON][i] = getItemIcon(id);
            } catch (Exception e) {
                exceptionsDuringCachePopulation.add(e);
                cells[CELL_ICON][i] = null;
            }
        }

        GeneratedRow generatedRow = rowGenerator != null ? rowGenerator
                .generateRow(this, id) : null;
        cells[CELL_GENERATED_ROW][i] = generatedRow;

        for (int j = 0; j < cols; j++) {
            if (isColumnCollapsed(colids[j])) {
                continue;
            }
            Property<?> p = null;
            Object value = "";
            boolean isGeneratedRow = generatedRow != null;
            boolean isGeneratedColumn = columnGenerators.containsKey(colids[j]);
            boolean isGenerated = isGeneratedRow || isGeneratedColumn;

            if (!isGenerated) {
                try {
                    p = getContainerProperty(id, colids[j]);
                } catch (Exception e) {
                    exceptionsDuringCachePopulation.add(e);
                    value = null;
                }
            }

            if (isGeneratedRow) {
                if (generatedRow.isSpanColumns() && j > 0) {
                    value = null;
                } else if (generatedRow.isSpanColumns() && j == 0
                        && generatedRow.getValue() instanceof Component) {
                    value = generatedRow.getValue();
                } else if (generatedRow.getText().length > j) {
                    value = generatedRow.getText()[j];
                }
            } else {
                // check if current pageBuffer already has row
                int index = firstIndex + i;
                if (p != null || isGenerated) {
                    int indexInOldBuffer = index - pageBufferFirstIndex;
                    if (index < firstIndexNotInCache
                            && index >= pageBufferFirstIndex
                            && pageBuffer[CELL_GENERATED_ROW][indexInOldBuffer] == null
                            && id.equals(pageBuffer[CELL_ITEMID][indexInOldBuffer])) {
                        // we already have data in our cache,
                        // recycle it instead of fetching it via
                        // getValue/getPropertyValue
                        value = pageBuffer[CELL_FIRSTCOL + j][indexInOldBuffer];
                        if (!isGeneratedColumn && iscomponent[j]
                                || !(value instanceof Component)) {
                            listenProperty(p, oldListenedProperties);
                        }
                    } else {
                        if (isGeneratedColumn) {
                            ColumnGenerator cg = columnGenerators
                                    .get(colids[j]);
                            try {
                                value = cg.generateCell(this, id, colids[j]);
                            } catch (Exception e) {
                                exceptionsDuringCachePopulation.add(e);
                                value = null;
                            }
                            if (value != null && !(value instanceof Component)
                                    && !(value instanceof String)) {
                                // Avoid errors if a generator returns
                                // something
                                // other than a Component or a String
                                value = value.toString();
                            }
                        } else if (iscomponent[j]) {
                            try {
                                value = p.getValue();
                            } catch (Exception e) {
                                exceptionsDuringCachePopulation.add(e);
                                value = null;
                            }
                            listenProperty(p, oldListenedProperties);
                        } else if (p != null) {
                            try {
                                value = getPropertyValue(id, colids[j], p);
                            } catch (Exception e) {
                                exceptionsDuringCachePopulation.add(e);
                                value = null;
                            }
                            /*
                             * If returned value is Component (via fieldfactory
                             * or overridden getPropertyValue) we expect it to
                             * listen property value changes. Otherwise if
                             * property emits value change events, table will
                             * start to listen them and refresh content when
                             * needed.
                             */
                            if (!(value instanceof Component)) {
                                listenProperty(p, oldListenedProperties);
                            }
                        } else {
                            try {
                                value = getPropertyValue(id, colids[j], null);
                            } catch (Exception e) {
                                exceptionsDuringCachePopulation.add(e);
                                value = null;
                            }
                        }
                    }
                }
            }

            if (value instanceof Component) {
                registerComponent((Component) value);
            }
            cells[CELL_FIRSTCOL + j][i] = value;
        }
    }

    /** Register component.
	 *
	 * @param component
	 *            the component
	 */
    protected void registerComponent(Component component) {
        getLogger().log(
                Level.FINEST,
                "Registered {0}: {1}",
                new Object[] { component.getClass().getSimpleName(),
                        component.getCaption() });
        if (!equals(component.getParent())) {
            component.setParent(this);
        }
        visibleComponents.add(component);
    }

    /** Listen property.
	 *
	 * @param p
	 *            the p
	 * @param oldListenedProperties
	 *            the old listened properties
	 */
    private void listenProperty(Property<?> p,
            HashSet<Property<?>> oldListenedProperties) {
        if (p instanceof Property.ValueChangeNotifier) {
            if (oldListenedProperties == null
                    || !oldListenedProperties.contains(p)) {
                ((Property.ValueChangeNotifier) p).addListener(this);
            }
            /*
             * register listened properties, so we can do proper cleanup to free
             * memory. Essential if table has loads of data and it is used for a
             * long time.
             */
            listenedProperties.add(p);

        }
    }

    /** Unregister components and properties in rows.
	 *
	 * @param firstIx
	 *            Index of the first row to process. Global index, not relative
	 *            to page buffer.
	 * @param count
	 *            the count
	 */
    private void unregisterComponentsAndPropertiesInRows(int firstIx, int count) {
        if (getLogger().isLoggable(Level.FINEST)) {
            getLogger().log(Level.FINEST,
                    "Unregistering components in rows {0}-{1}",
                    new Object[] { firstIx, (firstIx + count - 1) });
        }
        Object[] colids = getVisibleColumns();
        if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) {
            int bufSize = pageBuffer[CELL_ITEMID].length;
            int ix = firstIx - pageBufferFirstIndex;
            ix = ix < 0 ? 0 : ix;
            if (ix < bufSize) {
                count = count > bufSize - ix ? bufSize - ix : count;
                for (int i = 0; i < count; i++) {
                    for (int c = 0; c < colids.length; c++) {
                        Object cellVal = pageBuffer[CELL_FIRSTCOL + c][i + ix];
                        if (cellVal instanceof Component
                                && visibleComponents.contains(cellVal)) {
                            visibleComponents.remove(cellVal);
                            unregisterComponent((Component) cellVal);
                        } else {
                            Property<?> p = getContainerProperty(
                                    pageBuffer[CELL_ITEMID][i + ix], colids[c]);
                            if (p instanceof ValueChangeNotifier
                                    && listenedProperties.contains(p)) {
                                listenedProperties.remove(p);
                                ((ValueChangeNotifier) p).removeListener(this);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Helper method to remove listeners and maintain correct component
     * hierarchy. Detaches properties and components if those are no more
     * rendered in client.
     * 
     * @param oldListenedProperties
     *            set of properties that where listened in last render
     * @param oldVisibleComponents
     *            set of components that where attached in last render
     */
    private void unregisterPropertiesAndComponents(
            HashSet<Property<?>> oldListenedProperties,
            HashSet<Component> oldVisibleComponents) {
        if (oldVisibleComponents != null) {
            for (final Iterator<Component> i = oldVisibleComponents.iterator(); i
                    .hasNext();) {
                Component c = i.next();
                if (!visibleComponents.contains(c)) {
                    unregisterComponent(c);
                }
            }
        }

        if (oldListenedProperties != null) {
            for (final Iterator<Property<?>> i = oldListenedProperties
                    .iterator(); i.hasNext();) {
                Property.ValueChangeNotifier o = (ValueChangeNotifier) i.next();
                if (!listenedProperties.contains(o)) {
                    o.removeListener(this);
                }
            }
        }
    }

    /** This method cleans up a Component that has been generated when
	 * CustomTable is in editable mode. The component needs to be detached from
	 * its parent and if it is a field, it needs to be detached from its
	 * property data source in order to allow garbage collection to take care of
	 * removing the unused component from memory.
	 * 
	 * Override this method and getPropertyValue(Object, Object, Property) with
	 * custom logic if you need to deal with buffered fields.
	 *
	 * @param component
	 *            the component
	 * @see #getPropertyValue(Object, Object, Property)
	 */
    protected void unregisterComponent(Component component) {
        getLogger().log(
                Level.FINEST,
                "Unregistered {0}: {1}",
                new Object[] { component.getClass().getSimpleName(),
                        component.getCaption() });
        component.setParent(null);
        /*
         * Also remove property data sources to unregister listeners keeping the
         * fields in memory.
         */
        if (component instanceof Field) {
            Field<?> field = (Field<?>) component;
            Property<?> associatedProperty = associatedProperties
                    .remove(component);
            if (associatedProperty != null
                    && field.getPropertyDataSource() == associatedProperty) {
                // Remove the property data source only if it's the one we
                // added in getPropertyValue
                field.setPropertyDataSource(null);
            }
        }
    }

    /**
     * Sets the row header mode.
     * <p>
     * The mode can be one of the following ones:
     * <ul>
     * <li>{@link #ROW_HEADER_MODE_HIDDEN}: The row captions are hidden.</li>
     * <li>{@link #ROW_HEADER_MODE_ID}: Items Id-objects <code>toString()</code>
     * is used as row caption.
     * <li>{@link #ROW_HEADER_MODE_ITEM}: Item-objects <code>toString()</code>
     * is used as row caption.
     * <li>{@link #ROW_HEADER_MODE_PROPERTY}: Property set with
     * {@link #setItemCaptionPropertyId(Object)} is used as row header.
     * <li>{@link #ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID}: Items Id-objects
     * <code>toString()</code> is used as row header. If caption is explicitly
     * specified, it overrides the id-caption.
     * <li>{@link #ROW_HEADER_MODE_EXPLICIT}: The row headers must be explicitly
     * specified.</li>
     * <li>{@link #ROW_HEADER_MODE_INDEX}: The index of the item is used as row
     * caption. The index mode can only be used with the containers implementing
     * <code>Container.Indexed</code> interface.</li>
     * </ul>
     * The default value is {@link #ROW_HEADER_MODE_HIDDEN}
     * 
     * 
     * @param mode
     *            the One of the modes listed above.
     */
    public void setRowHeaderMode(RowHeaderMode mode) {
        if (mode != null) {
            rowHeaderMode = mode;
            if (mode != RowHeaderMode.HIDDEN) {
                setItemCaptionMode(mode.getItemCaptionMode());
            }
            // Assures the visual refresh. No need to reset the page buffer
            // before
            // as the content has not changed, only the alignments.
            refreshRenderedCells();
        }
    }

    /**
     * Gets the row header mode.
     * 
     * @return the Row header mode.
     * @see #setRowHeaderMode
     */
    public RowHeaderMode getRowHeaderMode() {
        return rowHeaderMode;
    }

    /** Adds the new row to table and fill the visible cells (except
	 * generated columns) with given values.
	 *
	 * @param cells
	 *            the Object array that is used for filling the visible cells
	 *            new row. The types must be settable to visible column property
	 *            types.
	 * @param itemId
	 *            the Id the new row. If null, a new id is automatically
	 *            assigned. If given, the table cant already have a item with
	 *            given id.
	 * @return Returns item id for the new row. Returns null if operation fails.
	 * @throws UnsupportedOperationException
	 *             the unsupported operation exception
	 */
    public Object addItem(Object[] cells, Object itemId)
            throws UnsupportedOperationException {

        // remove generated columns from the list of columns being assigned
        final LinkedList<Object> availableCols = new LinkedList<>();
        for (Iterator<Object> it = visibleColumns.iterator(); it.hasNext();) {
            Object id = it.next();
            if (!columnGenerators.containsKey(id)) {
                availableCols.add(id);
            }
        }
        // Checks that a correct number of cells are given
        if (cells.length != availableCols.size()) {
            return null;
        }

        // Creates new item
        Item item;
        if (itemId == null) {
            itemId = items.addItem();
            if (itemId == null) {
                return null;
            }
            item = items.getItem(itemId);
        } else {
            item = items.addItem(itemId);
        }
        if (item == null) {
            return null;
        }

        // Fills the item properties
        for (int i = 0; i < availableCols.size(); i++) {
            item.getItemProperty(availableCols.get(i)).setValue(cells[i]);
        }

        if (!(items instanceof Container.ItemSetChangeNotifier)) {
            refreshRowCache();
        }

        return itemId;
    }

    /**
     * Discards and recreates the internal row cache. Call this if you make
     * changes that affect the rows but the information about the changes are
     * not automatically propagated to the CustomTable.
     * <p>
     * Do not call this e.g. if you have updated the data model through a
     * Property. These types of changes are automatically propagated to the
     * CustomTable.
     * <p>
     * A typical case when this is needed is if you update a generator (e.g.
     * CellStyleGenerator) and want to ensure that the rows are redrawn with new
     * styles.
     * <p>
     * <i>Note that calling this method is not cheap so avoid calling it
     * unnecessarily.</i>
     * 
     * @since 6.7.2
     */
    public void refreshRowCache() {
        resetPageBuffer();
        refreshRenderedCells();
    }

    /**
     * Sets the Container that serves as the data source of the viewer. As a
     * side-effect the table's selection value is set to null as the old
     * selection might not exist in new Container.<br>
     * <br>
     * All rows and columns are generated as visible using this method. If the
     * new container contains properties that are not meant to be shown you
     * should use
     * {@link CustomTable#setContainerDataSource(Container, Collection)}
     * instead, especially if the table is editable.
     * <p>
     * Keeps propertyValueConverters if the corresponding id exists in the new
     * data source and is of a compatible type.
     * 
     * 
     * @param newDataSource
     *            the new data source.
     */
    @Override
    public void setContainerDataSource(Container newDataSource) {
        if (newDataSource == null) {
            newDataSource = new IndexedContainer();
        }
        Collection<Object> generated;
        if (columnGenerators != null) {
            generated = columnGenerators.keySet();
        } else {
            generated = Collections.emptyList();
        }
        List<Object> visibleIds = new ArrayList<>();
        if (generated.isEmpty()) {
            visibleIds.addAll(newDataSource.getContainerPropertyIds());
        } else {
            for (Object id : newDataSource.getContainerPropertyIds()) {
                // don't add duplicates
                if (!generated.contains(id)) {
                    visibleIds.add(id);
                }
            }
            // generated columns to the end
            visibleIds.addAll(generated);
        }
        setContainerDataSource(newDataSource, visibleIds);
    }

    /** Sets the container data source and the columns that will be visible.
	 * Columns are shown in the collection's iteration order.
	 * <p>
	 * Keeps propertyValueConverters if the corresponding id exists in the new
	 * data source and is of a compatible type.
	 *
	 * @param newDataSource
	 *            the new data source.
	 * @param visibleIds
	 *            IDs of the visible columns
	 * @see CustomTable#setContainerDataSource(Container)
	 * @see CustomTable#setVisibleColumns(Object[])
	 * @see CustomTable#setConverter(Object, Converter)
	 */
    public void setContainerDataSource(Container newDataSource,
            Collection<?> visibleIds) {

        disableContentRefreshing();

        if (newDataSource == null) {
            newDataSource = new IndexedContainer();
        }
        if (visibleIds == null) {
            visibleIds = new ArrayList<>();
        }

        // Retain propertyValueConverters if their corresponding ids are
        // properties of the new
        // data source and are of a compatible type
        if (propertyValueConverters != null) {
            Collection<?> newPropertyIds = newDataSource
                    .getContainerPropertyIds();
            LinkedList<Object> retainableValueConverters = new LinkedList<>();
            for (Object propertyId : newPropertyIds) {
                Converter<String, ?> converter = getConverter(propertyId);
                if (converter != null) {
                    if (typeIsCompatible(converter.getModelType(),
                            newDataSource.getType(propertyId))) {
                        retainableValueConverters.add(propertyId);
                    }
                }
            }
            propertyValueConverters.keySet().retainAll(
                    retainableValueConverters);
        }

        // Assures that the data source is ordered by making unordered
        // containers ordered by wrapping them
        if (newDataSource instanceof Container.Ordered) {
            super.setContainerDataSource(newDataSource);
        } else {
            super.setContainerDataSource(new ContainerOrderedWrapper(
                    newDataSource));
        }

        // Resets page position
        currentPageFirstItemId = null;
        currentPageFirstItemIndex = 0;

        // Resets column properties
        if (collapsedColumns != null) {
            collapsedColumns.clear();
        }

        // don't add the same id twice
        Collection<Object> col = new LinkedList<>();
        for (Iterator<?> it = visibleIds.iterator(); it.hasNext();) {
            Object id = it.next();
            if (!col.contains(id)) {
                col.add(id);
            }
        }

        setVisibleColumns(col.toArray());

        // Assure visual refresh
        resetPageBuffer();

        enableContentRefreshing(true);
    }

    /** Checks if class b can be safely assigned to class a.
	 *
	 * @param a
	 *            the a
	 * @param b
	 *            the b
	 * @return true, if successful
	 */
    private boolean typeIsCompatible(Class<?> a, Class<?> b) {
        // TODO Implement this check properly
        // Basically we need to do a a.isAssignableFrom(b)
        // with special considerations for primitive types.
        return true;
    }

    /** Gets items ids from a range of key values.
	 *
	 * @param itemId
	 *            the item id
	 * @param length
	 *            the length
	 * @return the item ids in range
	 */
    private LinkedHashSet<Object> getItemIdsInRange(Object itemId,
            final int length) {
        LinkedHashSet<Object> ids = new LinkedHashSet<>();
        for (int i = 0; i < length; i++) {
            assert itemId != null; // should not be null unless client-server
                                   // are out of sync
            ids.add(itemId);
            itemId = nextItemId(itemId);
        }
        return ids;
    }

    /** Handles selection if selection is a multiselection.
	 *
	 * @param variables
	 *            The variables
	 */
    private void handleSelectedItems(Map<String, Object> variables) {
        final String[] ka = (String[]) variables.get("selected");
        final String[] ranges = (String[]) variables.get("selectedRanges");

        Set<Object> renderedButNotSelectedItemIds = getCurrentlyRenderedItemIds();

        @SuppressWarnings("unchecked")
        HashSet<Object> newValue = new LinkedHashSet<>(
                (Collection<Object>) getValue());

        if (variables.containsKey("clearSelections")) {
            // the client side has instructed to swipe all previous selections
            newValue.clear();
        }

        /*
         * Then add (possibly some of them back) rows that are currently
         * selected on the client side (the ones that the client side is aware
         * of).
         */
        for (int i = 0; i < ka.length; i++) {
            // key to id
            final Object id = itemIdMapper.get(ka[i]);
            if (!isNullSelectionAllowed()
                    && (id == null || id == getNullSelectionItemId())) {
                // skip empty selection if nullselection is not allowed
                markAsDirty();
            } else if (id != null && containsId(id)) {
                newValue.add(id);
                renderedButNotSelectedItemIds.remove(id);
            }
        }

        /* Add range items aka shift clicked multiselection areas */
        if (ranges != null) {
            for (String range : ranges) {
                String[] split = range.split("-");
                Object startItemId = itemIdMapper.get(split[0]);
                int length = Integer.valueOf(split[1]);
                LinkedHashSet<Object> itemIdsInRange = getItemIdsInRange(
                        startItemId, length);
                newValue.addAll(itemIdsInRange);
                renderedButNotSelectedItemIds.removeAll(itemIdsInRange);
            }
        }
        /*
         * finally clear all currently rendered rows (the ones that the client
         * side counterpart is aware of) that the client didn't send as selected
         */
        newValue.removeAll(renderedButNotSelectedItemIds);

        if (!isNullSelectionAllowed() && newValue.isEmpty()) {
            // empty selection not allowed, keep old value
            markAsDirty();
            return;
        }

        setValue(newValue, true);

    }

    /** Gets the currently rendered item ids.
	 *
	 * @return the currently rendered item ids
	 */
    private Set<Object> getCurrentlyRenderedItemIds() {
        HashSet<Object> ids = new HashSet<>();
        if (pageBuffer != null) {
            for (int i = 0; i < pageBuffer[CELL_ITEMID].length; i++) {
                ids.add(pageBuffer[CELL_ITEMID][i]);
            }
        }
        return ids;
    }

    /* Component basics */

    /** Invoked when the value of a variable has changed.
	 *
	 * @param source
	 *            the source
	 * @param variables
	 *            the variables
	 * @see com.vaadin.ui.Select#changeVariables(java.lang.Object,
	 *      java.util.Map)
	 */

    @Override
    public void changeVariables(Object source, Map<String, Object> variables) {

        boolean clientNeedsContentRefresh = false;

        handleClickEvent(variables);

        handleColumnResizeEvent(variables);

        handleColumnWidthUpdates(variables);

        disableContentRefreshing();

        if (!isSelectable() && variables.containsKey("selected")) {
            // Not-selectable is a special case, AbstractSelect does not support
            // TODO could be optimized.
            variables = new HashMap<>(variables);
            variables.remove("selected");
        }

        /*
         * The AbstractSelect cannot handle the multiselection properly, instead
         * we handle it ourself
         */
        else if (isSelectable() && isMultiSelect()
                && variables.containsKey("selected")
                && multiSelectMode == MultiSelectMode.DEFAULT) {
            handleSelectedItems(variables);
            variables = new HashMap<>(variables);
            variables.remove("selected");
        }

        super.changeVariables(source, variables);

        // Client might update the pagelength if CustomTable height is fixed
        if (variables.containsKey("pagelength")) {
            // Sets pageLength directly to avoid repaint that setter causes
            pageLength = (Integer) variables.get("pagelength");
        }

        // Page start index
        if (variables.containsKey("firstvisible")) {
            final Integer value = (Integer) variables.get("firstvisible");
            if (value != null) {
                setCurrentPageFirstItemIndex(value.intValue(), false);
            }
        }

        // Sets requested firstrow and rows for the next paint
        if (variables.containsKey("reqfirstrow")
                || variables.containsKey("reqrows")) {

            try {
                firstToBeRenderedInClient = ((Integer) variables
                        .get("firstToBeRendered")).intValue();
                lastToBeRenderedInClient = ((Integer) variables
                        .get("lastToBeRendered")).intValue();
            } catch (Exception e) {
                // FIXME: Handle exception
                getLogger().log(Level.FINER,
                        "Could not parse the first and/or last rows.", e);
            }

            // respect suggested rows only if table is not otherwise updated
            // (row caches emptied by other event)
            if (!containerChangeToBeRendered) {
                Integer value = (Integer) variables.get("reqfirstrow");
                if (value != null) {
                    reqFirstRowToPaint = value.intValue();
                }

                value = (Integer) variables.get("reqrows");
                if (value != null) {
                    reqRowsToPaint = value.intValue();
                    int size = size();
                    // sanity check

                    if (reqFirstRowToPaint >= size) {
                        reqFirstRowToPaint = size;
                    }

                    if (reqFirstRowToPaint + reqRowsToPaint > size) {
                        reqRowsToPaint = size - reqFirstRowToPaint;
                    }
                }
            }
            if (getLogger().isLoggable(Level.FINEST)) {
                getLogger().log(
                        Level.FINEST,
                        "Client wants rows {0}-{1}",
                        new Object[] { reqFirstRowToPaint,
                                (reqFirstRowToPaint + reqRowsToPaint - 1) });
            }
            clientNeedsContentRefresh = true;
        }

        if (isSortEnabled()) {
            // Sorting
            boolean doSort = false;
            if (variables.containsKey("sortcolumn")) {
                final String colId = (String) variables.get("sortcolumn");
                if (colId != null && !"".equals(colId) && !"null".equals(colId)) {
                    final Object id = columnIdMap.get(colId);
                    setSortContainerPropertyId(id, false);
                    doSort = true;
                }
            }
            if (variables.containsKey("sortascending")) {
                final boolean state = ((Boolean) variables.get("sortascending"))
                        .booleanValue();
                if (state != sortAscending) {
                    setSortAscending(state, false);
                    doSort = true;
                }
            }
            if (doSort) {
                this.sort();
                resetPageBuffer();
            }
        }

        // Dynamic column hide/show and order
        // Update visible columns
        if (isColumnCollapsingAllowed()) {
            if (variables.containsKey("collapsedcolumns")) {
                try {
                    final Object[] ids = (Object[]) variables
                            .get("collapsedcolumns");
                    Set<Object> idSet = new HashSet<>();
                    for (Object id : ids) {
                        idSet.add(columnIdMap.get(id.toString()));
                    }
                    for (final Iterator<Object> it = visibleColumns.iterator(); it
                            .hasNext();) {
                        Object propertyId = it.next();
                        if (isColumnCollapsed(propertyId)) {
                            if (!idSet.contains(propertyId)) {
                                setColumnCollapsed(propertyId, false);
                            }
                        } else if (idSet.contains(propertyId)) {
                            setColumnCollapsed(propertyId, true);
                        }
                    }
                } catch (final Exception e) {
                    // FIXME: Handle exception
                    getLogger().log(Level.FINER,
                            "Could not determine column collapsing state", e);
                }
                clientNeedsContentRefresh = true;
            }
        }
        if (isColumnReorderingAllowed()) {
            if (variables.containsKey("columnorder")) {
                try {
                    final Object[] ids = (Object[]) variables
                            .get("columnorder");
                    // need a real Object[], ids can be a String[]
                    final Object[] idsTemp = new Object[ids.length];
                    for (int i = 0; i < ids.length; i++) {
                        idsTemp[i] = columnIdMap.get(ids[i].toString());
                    }
                    setColumnOrder(idsTemp);
                    if (hasListeners(ColumnReorderEvent.class)) {
                        fireEvent(new ColumnReorderEvent(this));
                    }
                } catch (final Exception e) {
                    // FIXME: Handle exception
                    getLogger().log(Level.FINER,
                            "Could not determine column reordering state", e);
                }
                clientNeedsContentRefresh = true;
            }
        }

        enableContentRefreshing(clientNeedsContentRefresh);

        // Actions
        if (variables.containsKey("action")) {
            final StringTokenizer st = new StringTokenizer(
                    (String) variables.get("action"), ",");
            if (st.countTokens() == 2) {
                final Object itemId = itemIdMapper.get(st.nextToken());
                final Action action = actionMapper.get(st.nextToken());

                if (action != null && (itemId == null || containsId(itemId))
                        && actionHandlers != null) {
                    for (Handler ah : actionHandlers) {
                        ah.handleAction(action, this, itemId);
                    }
                }
            }
        }

    }

    /** Handles click event.
	 *
	 * @param variables
	 *            the variables
	 */
    private void handleClickEvent(Map<String, Object> variables) {

        // Item click event
        if (variables.containsKey("clickEvent")) {
            String key = (String) variables.get("clickedKey");
            Object itemId = itemIdMapper.get(key);
            Object propertyId = null;
            String colkey = (String) variables.get("clickedColKey");
            // click is not necessary on a property
            if (colkey != null) {
                propertyId = columnIdMap.get(colkey);
            }
            MouseEventDetails evt = MouseEventDetails
                    .deSerialize((String) variables.get("clickEvent"));
            Item item = getItem(itemId);
            if (item != null) {
                fireEvent(new ItemClickEvent(this, item, itemId, propertyId,
                        evt));
            }
        }

        // Header click event
        else if (variables.containsKey("headerClickEvent")) {

            MouseEventDetails details = MouseEventDetails
                    .deSerialize((String) variables.get("headerClickEvent"));

            Object cid = variables.get("headerClickCID");
            Object propertyId = null;
            if (cid != null) {
                propertyId = columnIdMap.get(cid.toString());
            }
            fireEvent(new HeaderClickEvent(this, propertyId, details));
        }

        // Footer click event
        else if (variables.containsKey("footerClickEvent")) {
            MouseEventDetails details = MouseEventDetails
                    .deSerialize((String) variables.get("footerClickEvent"));

            Object cid = variables.get("footerClickCID");
            Object propertyId = null;
            if (cid != null) {
                propertyId = columnIdMap.get(cid.toString());
            }
            fireEvent(new FooterClickEvent(this, propertyId, details));
        }
    }

    /** Handles the column resize event sent by the client.
	 *
	 * @param variables
	 *            the variables
	 */
    private void handleColumnResizeEvent(Map<String, Object> variables) {
        if (variables.containsKey("columnResizeEventColumn")) {
            Object cid = variables.get("columnResizeEventColumn");
            Object propertyId = null;
            if (cid != null) {
                propertyId = columnIdMap.get(cid.toString());

                Object prev = variables.get("columnResizeEventPrev");
                int previousWidth = -1;
                if (prev != null) {
                    previousWidth = Integer.valueOf(prev.toString());
                }

                Object curr = variables.get("columnResizeEventCurr");
                int currentWidth = -1;
                if (curr != null) {
                    currentWidth = Integer.valueOf(curr.toString());
                }

                fireColumnResizeEvent(propertyId, previousWidth, currentWidth);
            }
        }
    }

    /** Fire column resize event.
	 *
	 * @param propertyId
	 *            the property id
	 * @param previousWidth
	 *            the previous width
	 * @param currentWidth
	 *            the current width
	 */
    private void fireColumnResizeEvent(Object propertyId, int previousWidth,
            int currentWidth) {
        /*
         * Update the sizes on the server side. If a column previously had a
         * expand ratio and the user resized the column then the expand ratio
         * will be turned into a static pixel size.
         */
        setColumnWidth(propertyId, currentWidth);

        fireEvent(new ColumnResizeEvent(this, propertyId, previousWidth,
                currentWidth));
    }

    /** Handle column width updates.
	 *
	 * @param variables
	 *            the variables
	 */
    private void handleColumnWidthUpdates(Map<String, Object> variables) {
        if (variables.containsKey("columnWidthUpdates")) {
            String[] events = (String[]) variables.get("columnWidthUpdates");
            for (String str : events) {
                String[] eventDetails = str.split(":");
                Object propertyId = columnIdMap.get(eventDetails[0]);
                if (propertyId == null) {
                    propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
                }
                int width = Integer.valueOf(eventDetails[1]);
                setColumnWidth(propertyId, width);
            }
        }
    }

    /**
     * Go to mode where content updates are not done. This is due we want to
     * bypass expensive content for some reason (like when we know we may have
     * other content changes on their way).
     * 
     * @return true if content refresh flag was enabled prior this call
     */
    protected boolean disableContentRefreshing() {
        boolean wasDisabled = isContentRefreshesEnabled;
        isContentRefreshesEnabled = false;
        return wasDisabled;
    }

    /**
     * Go to mode where content content refreshing has effect.
     * 
     * @param refreshContent
     *            true if content refresh needs to be done
     */
    protected void enableContentRefreshing(boolean refreshContent) {
        isContentRefreshesEnabled = true;
        if (refreshContent) {
            refreshRenderedCells();
            // Ensure that client gets a response
            markAsDirty();
        }
    }

    /* (non-Javadoc)
     * @see com.vaadin.ui.AbstractField#beforeClientResponse(boolean)
     */
    @Override
    public void beforeClientResponse(boolean initial) {
        super.beforeClientResponse(initial);

        // Ensure pageBuffer is filled before sending the response to avoid
        // calls to markAsDirty during paint
        getVisibleCells();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.vaadin.ui.AbstractSelect#paintContent(com.vaadin.
     * terminal.PaintTarget)
     */

    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        isBeingPainted = true;
        try {
            doPaintContent(target);
        } finally {
            isBeingPainted = false;
        }
    }

    /** Do paint content.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void doPaintContent(PaintTarget target) throws PaintException {
        /*
         * Body actions - Actions which has the target null and can be invoked
         * by right clicking on the table body.
         */
        final Set<Action> actionSet = findAndPaintBodyActions(target);

        final Object[][] cells = getVisibleCells();
        int rows = findNumRowsToPaint(target, cells);

        int total = size();
        if (shouldHideNullSelectionItem()) {
            total--;
            rows--;
        }

        // CustomTable attributes
        paintTableAttributes(target, rows, total);

        paintVisibleColumnOrder(target);

        // Rows
        if (isPartialRowUpdate() && painted && !target.isFullRepaint()) {
            paintPartialRowUpdate(target, actionSet);
        } else if (target.isFullRepaint() || isRowCacheInvalidated()) {
            paintRows(target, cells, actionSet);
            setRowCacheInvalidated(false);
        }

        /*
         * Send the page buffer indexes to ensure that the client side stays in
         * sync. Otherwise we _might_ have the situation where the client side
         * discards too few or too many rows, causing out of sync issues.
         */
        int pageBufferLastIndex = pageBufferFirstIndex
                + pageBuffer[CELL_ITEMID].length - 1;
        target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST,
                pageBufferFirstIndex);
        target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_LAST,
                pageBufferLastIndex);

        paintSorting(target);

        resetVariablesAndPageBuffer(target);

        // Actions
        paintActions(target, actionSet);

        paintColumnOrder(target);

        // Available columns
        paintAvailableColumns(target);

        paintVisibleColumns(target);

        if (keyMapperReset) {
            keyMapperReset = false;
            target.addAttribute(TableConstants.ATTRIBUTE_KEY_MAPPER_RESET, true);
        }

        if (dropHandler != null) {
            dropHandler.getAcceptCriterion().paint(target);
        }

        painted = true;
    }

    /** Sets the row cache invalidated.
	 *
	 * @param invalidated
	 *            the new row cache invalidated
	 */
    private void setRowCacheInvalidated(boolean invalidated) {
        rowCacheInvalidated = invalidated;
    }

    /** Checks if is row cache invalidated.
	 *
	 * @return true, if is row cache invalidated
	 */
    protected boolean isRowCacheInvalidated() {
        return rowCacheInvalidated;
    }

    /** Paint partial row update.
	 *
	 * @param target
	 *            the target
	 * @param actionSet
	 *            the action set
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintPartialRowUpdate(PaintTarget target, Set<Action> actionSet)
            throws PaintException {
        paintPartialRowUpdates(target, actionSet);
        paintPartialRowAdditions(target, actionSet);
    }

    /** Paint partial row updates.
	 *
	 * @param target
	 *            the target
	 * @param actionSet
	 *            the action set
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintPartialRowUpdates(PaintTarget target,
            Set<Action> actionSet) throws PaintException {
        final boolean[] iscomponent = findCellsWithComponents();

        int firstIx = getFirstUpdatedItemIndex();
        int count = getUpdatedRowCount();

        target.startTag("urows");
        target.addAttribute("firsturowix", firstIx);
        target.addAttribute("numurows", count);

        // Partial row updates bypass the normal caching mechanism.
        Object[][] cells = getVisibleCellsUpdateCacheRows(firstIx, count);
        for (int indexInRowbuffer = 0; indexInRowbuffer < count; indexInRowbuffer++) {
            final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];

            if (shouldHideNullSelectionItem()) {
                // Remove null selection item if null selection is not allowed
                continue;
            }

            paintRow(target, cells, isEditable(), actionSet, iscomponent,
                    indexInRowbuffer, itemId);
        }
        target.endTag("urows");
        maybeThrowCacheUpdateExceptions();
    }

    /** Paint partial row additions.
	 *
	 * @param target
	 *            the target
	 * @param actionSet
	 *            the action set
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintPartialRowAdditions(PaintTarget target,
            Set<Action> actionSet) throws PaintException {
        final boolean[] iscomponent = findCellsWithComponents();

        int firstIx = getFirstAddedItemIndex();
        int count = getAddedRowCount();

        target.startTag("prows");

        if (!shouldHideAddedRows()) {
            getLogger().log(Level.FINEST,
                    "Paint rows for add. Index: {0}, count: {1}.",
                    new Object[] { firstIx, count });

            // Partial row additions bypass the normal caching mechanism.
            Object[][] cells = getVisibleCellsInsertIntoCache(firstIx, count);
            if (cells[0].length < count) {
                // delete the rows below, since they will fall beyond the cache
                // page.
                target.addAttribute("delbelow", true);
                count = cells[0].length;
            }

            for (int indexInRowbuffer = 0; indexInRowbuffer < count; indexInRowbuffer++) {
                final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];
                if (shouldHideNullSelectionItem()) {
                    // Remove null selection item if null selection is not
                    // allowed
                    continue;
                }

                paintRow(target, cells, isEditable(), actionSet, iscomponent,
                        indexInRowbuffer, itemId);
            }
        } else {
            getLogger().log(Level.FINEST,
                    "Paint rows for remove. Index: {0}, count: {1}.",
                    new Object[] { firstIx, count });
            removeRowsFromCacheAndFillBottom(firstIx, count);
            target.addAttribute("hide", true);
        }

        target.addAttribute("firstprowix", firstIx);
        target.addAttribute("numprows", count);
        target.endTag("prows");
        maybeThrowCacheUpdateExceptions();
    }

    /**
     * Subclass and override this to enable partial row updates and additions,
     * which bypass the normal caching mechanism. This is useful for e.g.
     * TreeTable.
     * 
     * @return true if this update is a partial row update, false if not. For
     *         plain CustomTable it is always false.
     */
    protected boolean isPartialRowUpdate() {
        return false;
    }

    /**
     * Subclass and override this to enable partial row additions, bypassing the
     * normal caching mechanism. This is useful for e.g. TreeTable, where
     * expanding a node should only fetch and add the items inside of that node.
     * 
     * @return The index of the first added item. For plain CustomTable it is
     *         always 0.
     */
    protected int getFirstAddedItemIndex() {
        return 0;
    }

    /**
     * Subclass and override this to enable partial row additions, bypassing the
     * normal caching mechanism. This is useful for e.g. TreeTable, where
     * expanding a node should only fetch and add the items inside of that node.
     * 
     * @return the number of rows to be added, starting at the index returned by
     *         {@link #getFirstAddedItemIndex()}. For plain CustomTable it is
     *         always 0.
     */
    protected int getAddedRowCount() {
        return 0;
    }

    /**
     * Subclass and override this to enable removing of rows, bypassing the
     * normal caching and lazy loading mechanism. This is useful for e.g.
     * TreeTable, when you need to hide certain rows as a node is collapsed.
     * 
     * This should return true if the rows pointed to by
     * {@link #getFirstAddedItemIndex()} and {@link #getAddedRowCount()} should
     * be hidden instead of added.
     * 
     * @return whether the rows to add (see {@link #getFirstAddedItemIndex()}
     *         and {@link #getAddedRowCount()}) should be added or hidden. For
     *         plain CustomTable it is always false.
     */
    protected boolean shouldHideAddedRows() {
        return false;
    }

    /**
     * Subclass and override this to enable partial row updates, bypassing the
     * normal caching and lazy loading mechanism. This is useful for updating
     * the state of certain rows, e.g. in the TreeTable the collapsed state of a
     * single node is updated using this mechanism.
     * 
     * @return the index of the first item to be updated. For plain CustomTable
     *         it is always 0.
     */
    protected int getFirstUpdatedItemIndex() {
        return 0;
    }

    /**
     * Subclass and override this to enable partial row updates, bypassing the
     * normal caching and lazy loading mechanism. This is useful for updating
     * the state of certain rows, e.g. in the TreeTable the collapsed state of a
     * single node is updated using this mechanism.
     * 
     * @return the number of rows to update, starting at the index returned by
     *         {@link #getFirstUpdatedItemIndex()}. For plain table it is always
     *         0.
     */
    protected int getUpdatedRowCount() {
        return 0;
    }

    /** Paint table attributes.
	 *
	 * @param target
	 *            the target
	 * @param rows
	 *            the rows
	 * @param total
	 *            the total
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintTableAttributes(PaintTarget target, int rows, int total)
            throws PaintException {
        paintTabIndex(target);
        paintDragMode(target);
        paintSelectMode(target);

        if (cacheRate != CACHE_RATE_DEFAULT) {
            target.addAttribute("cr", cacheRate);
        }

        target.addAttribute("cols", getVisibleColumns().length);
        target.addAttribute("rows", rows);

        target.addAttribute("firstrow",
                (reqFirstRowToPaint >= 0 ? reqFirstRowToPaint
                        : firstToBeRenderedInClient));
        target.addAttribute("totalrows", total);
        if (getPageLength() != 0) {
            target.addAttribute("pagelength", getPageLength());
        }
        if (areColumnHeadersEnabled()) {
            target.addAttribute("colheaders", true);
        }
        if (rowHeadersAreEnabled()) {
            target.addAttribute("rowheaders", true);
        }

        target.addAttribute("colfooters", columnFootersVisible);

        // The cursors are only shown on pageable table
        if (getCurrentPageFirstItemIndex() != 0 || getPageLength() > 0) {
            target.addVariable(this, "firstvisible",
                    getCurrentPageFirstItemIndex());
            target.addVariable(this, "firstvisibleonlastpage",
                    currentPageFirstItemIndexOnLastPage);
        }
    }

    /** Resets and paints "to be painted next" variables. Also reset
	 * pageBuffer
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void resetVariablesAndPageBuffer(PaintTarget target)
            throws PaintException {
        reqFirstRowToPaint = -1;
        reqRowsToPaint = -1;
        containerChangeToBeRendered = false;
        target.addVariable(this, "reqrows", reqRowsToPaint);
        target.addVariable(this, "reqfirstrow", reqFirstRowToPaint);
    }

    /** Are column headers enabled.
	 *
	 * @return true, if successful
	 */
    private boolean areColumnHeadersEnabled() {
        return getColumnHeaderMode() != ColumnHeaderMode.HIDDEN;
    }

    /** Paint visible columns.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintVisibleColumns(PaintTarget target) throws PaintException {
        target.startTag("visiblecolumns");
        if (rowHeadersAreEnabled()) {
            target.startTag("column");
            target.addAttribute("cid", ROW_HEADER_COLUMN_KEY);
            paintColumnWidth(target, ROW_HEADER_FAKE_PROPERTY_ID);
            paintColumnExpandRatio(target, ROW_HEADER_FAKE_PROPERTY_ID);
            target.endTag("column");
        }
        final Collection<?> sortables = getSortableContainerPropertyIds();
        for (Object colId : visibleColumns) {
            if (colId != null) {
                target.startTag("column");
                target.addAttribute("cid", columnIdMap.key(colId));
                final String head = getColumnHeader(colId);
                target.addAttribute("caption", (head != null ? head : ""));
                final String foot = getColumnFooter(colId);
                target.addAttribute("fcaption", (foot != null ? foot : ""));
                if (isColumnCollapsed(colId)) {
                    target.addAttribute("collapsed", true);
                }
                if (areColumnHeadersEnabled()) {
                    if (getColumnIcon(colId) != null) {
                        target.addAttribute("icon", getColumnIcon(colId));
                    }
                    if (sortables.contains(colId)) {
                        target.addAttribute("sortable", true);
                    }
                }
                if (!Align.LEFT.equals(getColumnAlignment(colId))) {
                    target.addAttribute("align", getColumnAlignment(colId)
                            .toString());
                }
                paintColumnWidth(target, colId);
                paintColumnExpandRatio(target, colId);
                target.endTag("column");
            }
        }
        target.endTag("visiblecolumns");
    }

    /** Paint available columns.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintAvailableColumns(PaintTarget target)
            throws PaintException {
        if (columnCollapsingAllowed) {
            final HashSet<Object> collapsedCols = new HashSet<>();
            for (Object colId : visibleColumns) {
                if (isColumnCollapsed(colId)) {
                    collapsedCols.add(colId);
                }
            }
            final String[] collapsedKeys = new String[collapsedCols.size()];
            int nextColumn = 0;
            for (Object colId : visibleColumns) {
                if (isColumnCollapsed(colId)) {
                    collapsedKeys[nextColumn++] = columnIdMap.key(colId);
                }
            }
            target.addVariable(this, "collapsedcolumns", collapsedKeys);

            final String[] noncollapsibleKeys = new String[noncollapsibleColumns
                    .size()];
            nextColumn = 0;
            for (Object colId : noncollapsibleColumns) {
                noncollapsibleKeys[nextColumn++] = columnIdMap.key(colId);
            }
            target.addVariable(this, "noncollapsiblecolumns",
                    noncollapsibleKeys);
        }

    }

    /** Paint actions.
	 *
	 * @param target
	 *            the target
	 * @param actionSet
	 *            the action set
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintActions(PaintTarget target, final Set<Action> actionSet)
            throws PaintException {
        if (!actionSet.isEmpty()) {
            target.addVariable(this, "action", "");
            target.startTag("actions");
            for (Action a : actionSet) {
                target.startTag("action");
                if (a.getCaption() != null) {
                    target.addAttribute("caption", a.getCaption());
                }
                if (a.getIcon() != null) {
                    target.addAttribute("icon", a.getIcon());
                }
                target.addAttribute("key", actionMapper.key(a));
                target.endTag("action");
            }
            target.endTag("actions");
        }
    }

    /** Paint column order.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintColumnOrder(PaintTarget target) throws PaintException {
        if (columnReorderingAllowed) {
            final String[] colorder = new String[visibleColumns.size()];
            int i = 0;
            for (Object colId : visibleColumns) {
                colorder[i++] = columnIdMap.key(colId);
            }
            target.addVariable(this, "columnorder", colorder);
        }
    }

    /** Paint sorting.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintSorting(PaintTarget target) throws PaintException {
        // Sorting
        if (getContainerDataSource() instanceof Container.Sortable) {
            target.addVariable(this, "sortcolumn",
                    columnIdMap.key(sortContainerPropertyId));
            target.addVariable(this, "sortascending", sortAscending);
        }
    }

    /** Paint rows.
	 *
	 * @param target
	 *            the target
	 * @param cells
	 *            the cells
	 * @param actionSet
	 *            the action set
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintRows(PaintTarget target, final Object[][] cells,
            final Set<Action> actionSet) throws PaintException {
        final boolean[] iscomponent = findCellsWithComponents();

        target.startTag("rows");
        // cells array contains all that are supposed to be visible on client,
        // but we'll start from the one requested by client
        int start = 0;
        if (reqFirstRowToPaint != -1 && firstToBeRenderedInClient != -1) {
            start = reqFirstRowToPaint - firstToBeRenderedInClient;
        }
        int end = cells[0].length;
        if (reqRowsToPaint != -1) {
            end = start + reqRowsToPaint;
        }
        // sanity check
        if (lastToBeRenderedInClient != -1 && lastToBeRenderedInClient < end) {
            end = lastToBeRenderedInClient + 1;
        }
        if (start > cells[CELL_ITEMID].length || start < 0) {
            start = 0;
        }
        if (end > cells[CELL_ITEMID].length) {
            end = cells[CELL_ITEMID].length;
        }

        for (int indexInRowbuffer = start; indexInRowbuffer < end; indexInRowbuffer++) {
            final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];

            if (shouldHideNullSelectionItem()) {
                // Remove null selection item if null selection is not allowed
                continue;
            }

            paintRow(target, cells, isEditable(), actionSet, iscomponent,
                    indexInRowbuffer, itemId);
        }
        target.endTag("rows");
    }

    /** Find cells with components.
	 *
	 * @return the boolean[]
	 */
    private boolean[] findCellsWithComponents() {
        final boolean[] isComponent = new boolean[visibleColumns.size()];
        int ix = 0;
        for (Object columnId : visibleColumns) {
            if (columnGenerators.containsKey(columnId)) {
                isComponent[ix++] = true;
            } else {
                final Class<?> colType = getType(columnId);
                isComponent[ix++] = colType != null
                        && Component.class.isAssignableFrom(colType);
            }
        }
        return isComponent;
    }

    /** Paint visible column order.
	 *
	 * @param target
	 *            the target
	 */
    private void paintVisibleColumnOrder(PaintTarget target) {
        // Visible column order
        final ArrayList<String> visibleColOrder = new ArrayList<>();
        for (Object columnId : visibleColumns) {
            if (!isColumnCollapsed(columnId)) {
                visibleColOrder.add(columnIdMap.key(columnId));
            }
        }
        target.addAttribute("vcolorder", visibleColOrder.toArray());
    }

    /** Find and paint body actions.
	 *
	 * @param target
	 *            the target
	 * @return the sets the
	 */
    private Set<Action> findAndPaintBodyActions(PaintTarget target) {
        Set<Action> actionSet = new LinkedHashSet<>();
        if (actionHandlers != null) {
            final ArrayList<String> keys = new ArrayList<>();
            for (Handler ah : actionHandlers) {
                // Getting actions for the null item, which in this case means
                // the body item
                final Action[] actions = ah.getActions(null, this);
                if (actions != null) {
                    for (Action action : actions) {
                        actionSet.add(action);
                        keys.add(actionMapper.key(action));
                    }
                }
            }
            target.addAttribute("alb", keys.toArray());
        }
        return actionSet;
    }

    /** Should hide null selection item.
	 *
	 * @return true, if successful
	 */
    private boolean shouldHideNullSelectionItem() {
        return !isNullSelectionAllowed() && getNullSelectionItemId() != null
                && containsId(getNullSelectionItemId());
    }

    /** Find num rows to paint.
	 *
	 * @param target
	 *            the target
	 * @param cells
	 *            the cells
	 * @return the int
	 * @throws PaintException
	 *             the paint exception
	 */
    private int findNumRowsToPaint(PaintTarget target, final Object[][] cells)
            throws PaintException {
        int rows;
        if (reqRowsToPaint >= 0) {
            rows = reqRowsToPaint;
        } else {
            rows = cells[0].length;
            if (alwaysRecalculateColumnWidths) {
                // TODO experimental feature for now: tell the client to
                // recalculate column widths.
                // We'll only do this for paints that do not originate from
                // table scroll/cache requests (i.e when reqRowsToPaint<0)
                target.addAttribute("recalcWidths", true);
            }
        }
        return rows;
    }

    /** Paint select mode.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintSelectMode(PaintTarget target) throws PaintException {
        if (multiSelectMode != MultiSelectMode.DEFAULT) {
            target.addAttribute("multiselectmode", multiSelectMode.ordinal());
        }
        if (isSelectable()) {
            target.addAttribute("selectmode", (isMultiSelect() ? "multi"
                    : "single"));
        } else {
            target.addAttribute("selectmode", "none");
        }
        if (!isNullSelectionAllowed()) {
            target.addAttribute("nsa", false);
        }

        // selection support
        // The select variable is only enabled if selectable
        if (isSelectable()) {
            target.addVariable(this, "selected", findSelectedKeys());
        }
    }

    /** Find selected keys.
	 *
	 * @return the string[]
	 */
    private String[] findSelectedKeys() {
        LinkedList<String> selectedKeys = new LinkedList<>();
        if (isMultiSelect()) {
            HashSet<?> sel = new HashSet<Object>((Set<?>) getValue());
            Collection<?> vids = getVisibleItemIds();
            for (Iterator<?> it = vids.iterator(); it.hasNext();) {
                Object id = it.next();
                if (sel.contains(id)) {
                    selectedKeys.add(itemIdMapper.key(id));
                }
            }
        } else {
            Object value = getValue();
            if (value == null) {
                value = getNullSelectionItemId();
            }
            if (value != null) {
                selectedKeys.add(itemIdMapper.key(value));
            }
        }
        return selectedKeys.toArray(new String[selectedKeys.size()]);
    }

    /** Paint drag mode.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintDragMode(PaintTarget target) throws PaintException {
        if (dragMode != TableDragMode.NONE) {
            target.addAttribute("dragmode", dragMode.ordinal());
        }
    }

    /** Paint tab index.
	 *
	 * @param target
	 *            the target
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintTabIndex(PaintTarget target) throws PaintException {
        // The tab ordering number
        if (getTabIndex() > 0) {
            target.addAttribute("tabindex", getTabIndex());
        }
    }

    /** Paint column width.
	 *
	 * @param target
	 *            the target
	 * @param columnId
	 *            the column id
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintColumnWidth(PaintTarget target, final Object columnId)
            throws PaintException {
        if (columnWidths.containsKey(columnId)) {
            target.addAttribute("width", getColumnWidth(columnId));
        }
    }

    /** Paint column expand ratio.
	 *
	 * @param target
	 *            the target
	 * @param columnId
	 *            the column id
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintColumnExpandRatio(PaintTarget target,
            final Object columnId) throws PaintException {
        if (columnExpandRatios.containsKey(columnId)) {
            target.addAttribute("er", getColumnExpandRatio(columnId));
        }
    }

    /** Row headers are enabled.
	 *
	 * @return true, if successful
	 */
    private boolean rowHeadersAreEnabled() {
        return getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN;
    }

    /** Paint row.
	 *
	 * @param target
	 *            the target
	 * @param cells
	 *            the cells
	 * @param iseditable
	 *            the iseditable
	 * @param actionSet
	 *            the action set
	 * @param iscomponent
	 *            the iscomponent
	 * @param indexInRowbuffer
	 *            the index in rowbuffer
	 * @param itemId
	 *            the item id
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintRow(PaintTarget target, final Object[][] cells,
            final boolean iseditable, final Set<Action> actionSet,
            final boolean[] iscomponent, int indexInRowbuffer,
            final Object itemId) throws PaintException {
        target.startTag("tr");

        paintRowAttributes(target, cells, actionSet, indexInRowbuffer, itemId);

        // cells
        int currentColumn = 0;
        for (final Iterator<Object> it = visibleColumns.iterator(); it
                .hasNext(); currentColumn++) {
            final Object columnId = it.next();
            if (columnId == null || isColumnCollapsed(columnId)) {
                continue;
            }
            /*
             * For each cell, if a cellStyleGenerator is specified, get the
             * specific style for the cell. If there is any, add it to the
             * target.
             */
            if (cellStyleGenerator != null) {
                String cellStyle = cellStyleGenerator.getStyle(this, itemId,
                        columnId);
                if (cellStyle != null && !cellStyle.equals("")) {
                    target.addAttribute("style-" + columnIdMap.key(columnId),
                            cellStyle);
                }
            }

            if ((iscomponent[currentColumn] || iseditable || cells[CELL_GENERATED_ROW][indexInRowbuffer] != null)
                    && Component.class.isInstance(cells[CELL_FIRSTCOL
                            + currentColumn][indexInRowbuffer])) {
                final Component c = (Component) cells[CELL_FIRSTCOL
                        + currentColumn][indexInRowbuffer];
                if (c == null
                        || !LegacyCommunicationManager
                                .isComponentVisibleToClient(c)) {
                    target.addText("");
                } else {
                    LegacyPaint.paint(c, target);
                }
            } else {
                target.addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]);
            }
            paintCellTooltips(target, itemId, columnId);
        }

        target.endTag("tr");
    }

    /** Paint cell tooltips.
	 *
	 * @param target
	 *            the target
	 * @param itemId
	 *            the item id
	 * @param columnId
	 *            the column id
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintCellTooltips(PaintTarget target, Object itemId,
            Object columnId) throws PaintException {
        if (itemDescriptionGenerator != null) {
            String itemDescription = itemDescriptionGenerator
                    .generateDescription(this, itemId, columnId);
            if (itemDescription != null && !itemDescription.equals("")) {
                target.addAttribute("descr-" + columnIdMap.key(columnId),
                        itemDescription);
            }
        }
    }

    /** Paint row tooltips.
	 *
	 * @param target
	 *            the target
	 * @param itemId
	 *            the item id
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintRowTooltips(PaintTarget target, Object itemId)
            throws PaintException {
        if (itemDescriptionGenerator != null) {
            String rowDescription = itemDescriptionGenerator
                    .generateDescription(this, itemId, null);
            if (rowDescription != null && !rowDescription.equals("")) {
                target.addAttribute("rowdescr", rowDescription);
            }
        }
    }

    /** Paint row attributes.
	 *
	 * @param target
	 *            the target
	 * @param cells
	 *            the cells
	 * @param actionSet
	 *            the action set
	 * @param indexInRowbuffer
	 *            the index in rowbuffer
	 * @param itemId
	 *            the item id
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintRowAttributes(PaintTarget target, final Object[][] cells,
            final Set<Action> actionSet, int indexInRowbuffer,
            final Object itemId) throws PaintException {
        // tr attributes

        paintRowIcon(target, cells, indexInRowbuffer);
        paintRowHeader(target, cells, indexInRowbuffer);
        paintGeneratedRowInfo(target, cells, indexInRowbuffer);
        target.addAttribute("key",
                Integer.parseInt(cells[CELL_KEY][indexInRowbuffer].toString()));

        if (isSelected(itemId)) {
            target.addAttribute("selected", true);
        }

        // Actions
        if (actionHandlers != null) {
            final ArrayList<String> keys = new ArrayList<>();
            for (Handler ah : actionHandlers) {
                final Action[] aa = ah.getActions(itemId, this);
                if (aa != null) {
                    for (int ai = 0; ai < aa.length; ai++) {
                        final String key = actionMapper.key(aa[ai]);
                        actionSet.add(aa[ai]);
                        keys.add(key);
                    }
                }
            }
            target.addAttribute("al", keys.toArray());
        }

        /*
         * For each row, if a cellStyleGenerator is specified, get the specific
         * style for the cell, using null as propertyId. If there is any, add it
         * to the target.
         */
        if (cellStyleGenerator != null) {
            String rowStyle = cellStyleGenerator.getStyle(this, itemId, null);
            if (rowStyle != null && !rowStyle.equals("")) {
                target.addAttribute("rowstyle", rowStyle);
            }
        }

        paintRowTooltips(target, itemId);

        paintRowAttributes(target, itemId);
    }

    /** Paint generated row info.
	 *
	 * @param target
	 *            the target
	 * @param cells
	 *            the cells
	 * @param indexInRowBuffer
	 *            the index in row buffer
	 * @throws PaintException
	 *             the paint exception
	 */
    private void paintGeneratedRowInfo(PaintTarget target, Object[][] cells,
            int indexInRowBuffer) throws PaintException {
        GeneratedRow generatedRow = (GeneratedRow) cells[CELL_GENERATED_ROW][indexInRowBuffer];
        if (generatedRow != null) {
            target.addAttribute("gen_html", generatedRow.isHtmlContentAllowed());
            target.addAttribute("gen_span", generatedRow.isSpanColumns());
            target.addAttribute("gen_widget",
                    generatedRow.getValue() instanceof Component);
        }
    }

    /** Paint row header.
	 *
	 * @param target
	 *            the target
	 * @param cells
	 *            the cells
	 * @param indexInRowbuffer
	 *            the index in rowbuffer
	 * @throws PaintException
	 *             the paint exception
	 */
    protected void paintRowHeader(PaintTarget target, Object[][] cells,
            int indexInRowbuffer) throws PaintException {
        if (rowHeadersAreEnabled()) {
            if (cells[CELL_HEADER][indexInRowbuffer] != null) {
                target.addAttribute("caption",
                        (String) cells[CELL_HEADER][indexInRowbuffer]);
            }
        }

    }

    /** Paint row icon.
	 *
	 * @param target
	 *            the target
	 * @param cells
	 *            the cells
	 * @param indexInRowbuffer
	 *            the index in rowbuffer
	 * @throws PaintException
	 *             the paint exception
	 */
    protected void paintRowIcon(PaintTarget target, final Object[][] cells,
            int indexInRowbuffer) throws PaintException {
        if (rowHeadersAreEnabled()
                && cells[CELL_ICON][indexInRowbuffer] != null) {
            target.addAttribute("icon",
                    (Resource) cells[CELL_ICON][indexInRowbuffer]);
        }
    }

    /** A method where extended CustomTable implementations may add their
	 * custom attributes for rows.
	 *
	 * @param target
	 *            the target
	 * @param itemId
	 *            the item id
	 * @throws PaintException
	 *             the paint exception
	 */
    protected void paintRowAttributes(PaintTarget target, Object itemId)
            throws PaintException {

    }

    /**
     * Gets the cached visible table contents.
     * 
     * @return the cached visible table contents.
     */
    private Object[][] getVisibleCells() {
        if (pageBuffer == null) {
            refreshRenderedCells();
        }
        return pageBuffer;
    }

    /**
     * Gets the value of property.
     * 
     * By default if the table is editable the fieldFactory is used to create
     * editors for table cells. Otherwise formatPropertyValue is used to format
     * the value representation.
     * 
     * @param rowId
     *            the Id of the row (same as item Id).
     * @param colId
     *            the Id of the column.
     * @param property
     *            the Property to be presented.
     * @return Object Either formatted value or Component for field.
     * @see #setTableFieldFactory(TableFieldFactory)
     */
    protected Object getPropertyValue(Object rowId, Object colId,
            Property property) {
        if (isEditable() && fieldFactory != null) {
            final Field<?> f = fieldFactory.createField(
                    getContainerDataSource(), rowId, colId, this);
            if (f != null) {
                // Remember that we have made this association so we can remove
                // it when the component is removed
                associatedProperties.put(f, property);
                bindPropertyToField(rowId, colId, property, f);
                return f;
            }
        }

        return formatPropertyValue(rowId, colId, property);
    }

    /** Binds an item property to a field generated by TableFieldFactory. The
	 * default behavior is to bind property straight to Field. If
	 * Property.Viewer type property (e.g. PropertyFormatter) is already set for
	 * field, the property is bound to that Property.Viewer.
	 *
	 * @param rowId
	 *            the row id
	 * @param colId
	 *            the col id
	 * @param property
	 *            the property
	 * @param field
	 *            the field
	 * @since 6.7.3
	 */
    protected void bindPropertyToField(Object rowId, Object colId,
            Property property, Field field) {
        // check if field has a property that is Viewer set. In that case we
        // expect developer has e.g. PropertyFormatter that he wishes to use and
        // assign the property to the Viewer instead.
        boolean hasFilterProperty = field.getPropertyDataSource() != null
                && (field.getPropertyDataSource() instanceof Property.Viewer);
        if (hasFilterProperty) {
            ((Property.Viewer) field.getPropertyDataSource())
                    .setPropertyDataSource(property);
        } else {
            field.setPropertyDataSource(property);
        }
    }

    /**
     * Formats table cell property values. By default the property.toString()
     * and return a empty string for null properties.
     * 
     * @param rowId
     *            the Id of the row (same as item Id).
     * @param colId
     *            the Id of the column.
     * @param property
     *            the Property to be formatted.
     * @return the String representation of property and its value.
     * @since 3.1
     */
    protected String formatPropertyValue(Object rowId, Object colId,
            Property<?> property) {
        if (property == null) {
            return "";
        }
        Converter<String, Object> converter = null;

        if (hasConverter(colId)) {
            converter = getConverter(colId);
        } else {
            converter = (Converter) ConverterUtil.getConverter(String.class,
                    property.getType(), getSession());
        }
        Object value = property.getValue();
        if (converter != null) {
            return converter.convertToPresentation(value, String.class,
                    getLocale());
        }
        return (null != value) ? value.toString() : "";
    }

    /* Action container */

    /** Registers a new action handler for this container.
	 *
	 * @param actionHandler
	 *            the action handler
	 * @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler)
	 */

    @Override
    public void addActionHandler(Action.Handler actionHandler) {

        if (actionHandler != null) {

            if (actionHandlers == null) {
                actionHandlers = new LinkedList<>();
                actionMapper = new KeyMapper<>();
            }

            if (!actionHandlers.contains(actionHandler)) {
                actionHandlers.add(actionHandler);
                // Assures the visual refresh. No need to reset the page buffer
                // before as the content has not changed, only the action
                // handlers.
                refreshRenderedCells();
            }

        }
    }

    /** Removes a previously registered action handler for the contents of
	 * this container.
	 *
	 * @param actionHandler
	 *            the action handler
	 * @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler)
	 */

    @Override
    public void removeActionHandler(Action.Handler actionHandler) {

        if (actionHandlers != null && actionHandlers.contains(actionHandler)) {

            actionHandlers.remove(actionHandler);

            if (actionHandlers.isEmpty()) {
                actionHandlers = null;
                actionMapper = null;
            }

            // Assures the visual refresh. No need to reset the page buffer
            // before as the content has not changed, only the action
            // handlers.
            refreshRenderedCells();
        }
    }

    /** Removes all action handlers.
	 */
    public void removeAllActionHandlers() {
        actionHandlers = null;
        actionMapper = null;
        // Assures the visual refresh. No need to reset the page buffer
        // before as the content has not changed, only the action
        // handlers.
        refreshRenderedCells();
    }

    /* Property value change listening support */

    /** Notifies this listener that the Property's value has changed.
	 * 
	 * Also listens changes in rendered items to refresh content area.
	 *
	 * @param event
	 *            the event
	 * @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
	 */

    @Override
    public void valueChange(Property.ValueChangeEvent event) {
        if (equals(event.getProperty())
                || event.getProperty() == getPropertyDataSource()) {
            super.valueChange(event);
        } else {
            refreshRowCache();
            containerChangeToBeRendered = true;
        }
        markAsDirty();
    }

    /**
     * Clears the current page buffer. Call this before
     * {@link #refreshRenderedCells()} to ensure that all content is updated
     * from the properties.
     */
    protected void resetPageBuffer() {
        firstToBeRenderedInClient = -1;
        lastToBeRenderedInClient = -1;
        reqFirstRowToPaint = -1;
        reqRowsToPaint = -1;
        pageBuffer = null;
    }

    /**
     * Notifies the component that it is connected to an application.
     * 
     * @see com.vaadin.ui.Component#attach()
     */

    @Override
    public void attach() {
        super.attach();

        refreshRenderedCells();
    }

    /** Notifies the component that it is detached from the application.
	 *
	 * @see com.vaadin.ui.Component#detach()
	 */

    @Override
    public void detach() {
        super.detach();
    }

    /** Removes all Items from the Container.
	 *
	 * @return true, if successful
	 * @see com.vaadin.data.Container#removeAllItems()
	 */

    @Override
    public boolean removeAllItems() {
        currentPageFirstItemId = null;
        currentPageFirstItemIndex = 0;
        return super.removeAllItems();
    }

    /** Removes the Item identified by <code>ItemId</code> from the
	 * Container.
	 *
	 * @param itemId
	 *            the item id
	 * @return true, if successful
	 * @see com.vaadin.data.Container#removeItem(Object)
	 */

    @Override
    public boolean removeItem(Object itemId) {
        final Object nextItemId = nextItemId(itemId);
        final boolean ret = super.removeItem(itemId);
        if (ret && (itemId != null) && (itemId.equals(currentPageFirstItemId))) {
            currentPageFirstItemId = nextItemId;
        }
        if (!(items instanceof Container.ItemSetChangeNotifier)) {
            refreshRowCache();
        }
        return ret;
    }

    /** Removes a Property specified by the given Property ID from the
	 * Container.
	 *
	 * @param propertyId
	 *            the property id
	 * @return true, if successful
	 * @throws UnsupportedOperationException
	 *             the unsupported operation exception
	 * @see com.vaadin.data.Container#removeContainerProperty(Object)
	 */

    @Override
    public boolean removeContainerProperty(Object propertyId)
            throws UnsupportedOperationException {

        // If a visible property is removed, remove the corresponding column
        visibleColumns.remove(propertyId);
        columnAlignments.remove(propertyId);
        columnIcons.remove(propertyId);
        columnHeaders.remove(propertyId);
        columnFooters.remove(propertyId);
        // If a propertyValueConverter was defined for the property, remove it.
        propertyValueConverters.remove(propertyId);

        return super.removeContainerProperty(propertyId);
    }

    /** Adds a new property to the table and show it as a visible column.
	 *
	 * @param propertyId
	 *            the Id of the proprty.
	 * @param type
	 *            the class of the property.
	 * @param defaultValue
	 *            the default value given for all existing items.
	 * @return true, if successful
	 * @throws UnsupportedOperationException
	 *             the unsupported operation exception
	 * @see com.vaadin.data.Container#addContainerProperty(Object, Class,
	 *      Object)
	 */

    @Override
    public boolean addContainerProperty(Object propertyId, Class<?> type,
            Object defaultValue) throws UnsupportedOperationException {

        boolean visibleColAdded = false;
        if (!visibleColumns.contains(propertyId)) {
            visibleColumns.add(propertyId);
            visibleColAdded = true;
        }

        if (!super.addContainerProperty(propertyId, type, defaultValue)) {
            if (visibleColAdded) {
                visibleColumns.remove(propertyId);
            }
            return false;
        }
        if (!(items instanceof Container.PropertySetChangeNotifier)) {
            refreshRowCache();
        }
        return true;
    }

    /** Adds a new property to the table and show it as a visible column.
	 *
	 * @param propertyId
	 *            the Id of the proprty
	 * @param type
	 *            the class of the property
	 * @param defaultValue
	 *            the default value given for all existing items
	 * @param columnHeader
	 *            the Explicit header of the column. If explicit header is not
	 *            needed, this should be set null.
	 * @param columnIcon
	 *            the Icon of the column. If icon is not needed, this should be
	 *            set null.
	 * @param columnAlignment
	 *            the Alignment of the column. Null implies align left.
	 * @return true, if successful
	 * @throws UnsupportedOperationException
	 *             if the operation is not supported.
	 * @see com.vaadin.data.Container#addContainerProperty(Object, Class,
	 *      Object)
	 */
    public boolean addContainerProperty(Object propertyId, Class<?> type,
            Object defaultValue, String columnHeader, Resource columnIcon,
            Align columnAlignment) throws UnsupportedOperationException {
        if (!this.addContainerProperty(propertyId, type, defaultValue)) {
            return false;
        }
        setColumnAlignment(propertyId, columnAlignment);
        setColumnHeader(propertyId, columnHeader);
        setColumnIcon(propertyId, columnIcon);
        return true;
    }

    /**
     * Adds a generated column to the CustomTable.
     * <p>
     * A generated column is a column that exists only in the CustomTable, not
     * as a property in the underlying Container. It shows up just as a regular
     * column.
     * 
     * <p>
     * A generated column will override a property with the same id, so that the
     * generated column is shown instead of the column representing the
     * property. Note that getContainerProperty() will still get the real
     * property.
     * 
     * <p>
     * CustomTable will not listen to value change events from properties
     * overridden by generated columns. If the content of your generated column
     * depends on properties that are not directly visible in the table, attach
     * value change listener to update the content on all depended properties.
     * Otherwise your UI might not get updated as expected.
     * 
     * <p>
     * Also note that getVisibleColumns() will return the generated columns,
     * while getContainerPropertyIds() will not.
     * 
     * 
     * @param id
     *            the id of the column to be added
     * @param generatedColumn
     *            the {@link ColumnGenerator} to use for this column
     */
    public void addGeneratedColumn(Object id, ColumnGenerator generatedColumn) {
        if (generatedColumn == null) {
            throw new IllegalArgumentException(
                    "Can not add null as a GeneratedColumn");
        }
        if (columnGenerators.containsKey(id)) {
            throw new IllegalArgumentException(
                    "Can not add the same GeneratedColumn twice, id:" + id);
        } else {
            columnGenerators.put(id, generatedColumn);
            /*
             * add to visible column list unless already there (overriding
             * column from DS)
             */
            if (!visibleColumns.contains(id)) {
                visibleColumns.add(id);
            }
            refreshRowCache();
        }
    }

    /** Returns the ColumnGenerator used to generate the given column.
	 *
	 * @param columnId
	 *            The id of the generated column
	 * @return The ColumnGenerator used for the given columnId or null.
	 * @throws IllegalArgumentException
	 *             the illegal argument exception
	 */
    public ColumnGenerator getColumnGenerator(Object columnId)
            throws IllegalArgumentException {
        return columnGenerators.get(columnId);
    }

    /**
     * Removes a generated column previously added with addGeneratedColumn.
     * 
     * @param columnId
     *            id of the generated column to remove
     * @return true if the column could be removed (existed in the CustomTable)
     */
    public boolean removeGeneratedColumn(Object columnId) {
        if (columnGenerators.containsKey(columnId)) {
            columnGenerators.remove(columnId);
            // remove column from visibleColumns list unless it exists in
            // container (generator previously overrode this column)
            if (!items.getContainerPropertyIds().contains(columnId)) {
                visibleColumns.remove(columnId);
            }
            refreshRowCache();
            return true;
        }
        return false;
    }

    /** Returns item identifiers of the items which are currently rendered on
	 * the client.
	 * <p>
	 * Note, that some due to historical reasons the name of the method is bit
	 * misleading. Some items may be partly or totally out of the viewport of
	 * the table's scrollable area. Actually detecting rows which can be
	 * actually seen by the end user may be problematic due to the client server
	 * architecture. Using {@link #getCurrentPageFirstItemId()} combined with
	 * {@link #getPageLength()} may produce good enough estimates in some
	 * situations.
	 *
	 * @return the visible item ids
	 * @see com.vaadin.ui.Select#getVisibleItemIds()
	 */

    @Override
    public Collection<?> getVisibleItemIds() {

        final LinkedList<Object> visible = new LinkedList<>();

        final Object[][] cells = getVisibleCells();
        // may be null if the table has not been rendered yet (e.g. not attached
        // to a layout)
        if (null != cells) {
            for (int i = 0; i < cells[CELL_ITEMID].length; i++) {
                visible.add(cells[CELL_ITEMID][i]);
            }
        }

        return visible;
    }

    /** Container datasource item set change. CustomTable must flush its
	 * buffers on change.
	 *
	 * @param event
	 *            the event
	 * @see com.vaadin.data.Container.ItemSetChangeListener#containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent)
	 */

    @Override
    public void containerItemSetChange(Container.ItemSetChangeEvent event) {
        if (isBeingPainted) {
            return;
        }

        super.containerItemSetChange(event);

        // super method clears the key map, must inform client about this to
        // avoid getting invalid keys back (#8584)
        keyMapperReset = true;

        // ensure that page still has first item in page, ignore buffer refresh
        // (forced in this method)
        setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex(), false);
        refreshRowCache();
    }

    /** Container datasource property set change. CustomTable must flush its
	 * buffers on change.
	 *
	 * @param event
	 *            the event
	 * @see com.vaadin.data.Container.PropertySetChangeListener#containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent)
	 */

    @Override
    public void containerPropertySetChange(
            Container.PropertySetChangeEvent event) {
        if (isBeingPainted) {
            return;
        }

        disableContentRefreshing();
        super.containerPropertySetChange(event);

        // sanitetize visibleColumns. note that we are not adding previously
        // non-existing properties as columns
        Collection<?> containerPropertyIds = getContainerDataSource()
                .getContainerPropertyIds();

        LinkedList<Object> newVisibleColumns = new LinkedList<>(
                visibleColumns);
        for (Iterator<Object> iterator = newVisibleColumns.iterator(); iterator
                .hasNext();) {
            Object id = iterator.next();
            if (!(containerPropertyIds.contains(id) || columnGenerators
                    .containsKey(id))) {
                iterator.remove();
            }
        }
        setVisibleColumns(newVisibleColumns.toArray());
        // same for collapsed columns
        for (Iterator<Object> iterator = collapsedColumns.iterator(); iterator
                .hasNext();) {
            Object id = iterator.next();
            if (!(containerPropertyIds.contains(id) || columnGenerators
                    .containsKey(id))) {
                iterator.remove();
            }
        }

        resetPageBuffer();
        enableContentRefreshing(true);
    }

    /** Adding new items is not supported.
	 *
	 * @param allowNewOptions
	 *            the new new items allowed
	 * @throws UnsupportedOperationException
	 *             if set to true.
	 * @see com.vaadin.ui.Select#setNewItemsAllowed(boolean)
	 */

    @Override
    public void setNewItemsAllowed(boolean allowNewOptions)
            throws UnsupportedOperationException {
        if (allowNewOptions) {
            throw new UnsupportedOperationException();
        }
    }

    /** Gets the ID of the Item following the Item that corresponds to
	 * itemId.
	 *
	 * @param itemId
	 *            the item id
	 * @return the object
	 * @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
	 */

    @Override
    public Object nextItemId(Object itemId) {
        return ((Container.Ordered) items).nextItemId(itemId);
    }

    /** Gets the ID of the Item preceding the Item that corresponds to the
	 * itemId.
	 *
	 * @param itemId
	 *            the item id
	 * @return the object
	 * @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
	 */

    @Override
    public Object prevItemId(Object itemId) {
        return ((Container.Ordered) items).prevItemId(itemId);
    }

    /** Gets the ID of the first Item in the Container.
	 *
	 * @return the object
	 * @see com.vaadin.data.Container.Ordered#firstItemId()
	 */

    @Override
    public Object firstItemId() {
        return ((Container.Ordered) items).firstItemId();
    }

    /** Gets the ID of the last Item in the Container.
	 *
	 * @return the object
	 * @see com.vaadin.data.Container.Ordered#lastItemId()
	 */

    @Override
    public Object lastItemId() {
        return ((Container.Ordered) items).lastItemId();
    }

    /** Tests if the Item corresponding to the given Item ID is the first
	 * Item in the Container.
	 *
	 * @param itemId
	 *            the item id
	 * @return true, if is first id
	 * @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
	 */

    @Override
    public boolean isFirstId(Object itemId) {
        return ((Container.Ordered) items).isFirstId(itemId);
    }

    /** Tests if the Item corresponding to the given Item ID is the last Item
	 * in the Container.
	 *
	 * @param itemId
	 *            the item id
	 * @return true, if is last id
	 * @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
	 */

    @Override
    public boolean isLastId(Object itemId) {
        return ((Container.Ordered) items).isLastId(itemId);
    }

    /** Adds new item after the given item.
	 *
	 * @param previousItemId
	 *            the previous item id
	 * @return the object
	 * @throws UnsupportedOperationException
	 *             the unsupported operation exception
	 * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
	 */

    @Override
    public Object addItemAfter(Object previousItemId)
            throws UnsupportedOperationException {
        Object itemId = ((Container.Ordered) items)
                .addItemAfter(previousItemId);
        if (!(items instanceof Container.ItemSetChangeNotifier)) {
            refreshRowCache();
        }
        return itemId;
    }

    /** Adds new item after the given item.
	 *
	 * @param previousItemId
	 *            the previous item id
	 * @param newItemId
	 *            the new item id
	 * @return the item
	 * @throws UnsupportedOperationException
	 *             the unsupported operation exception
	 * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
	 *      java.lang.Object)
	 */

    @Override
    public Item addItemAfter(Object previousItemId, Object newItemId)
            throws UnsupportedOperationException {
        Item item = ((Container.Ordered) items).addItemAfter(previousItemId,
                newItemId);
        if (!(items instanceof Container.ItemSetChangeNotifier)) {
            refreshRowCache();
        }
        return item;
    }

    /**
     * Sets the TableFieldFactory that is used to create editor for table cells.
     * 
     * The TableFieldFactory is only used if the CustomTable is editable. By
     * default the DefaultFieldFactory is used.
     * 
     * @param fieldFactory
     *            the field factory to set.
     * @see #isEditable
     * @see DefaultFieldFactory
     */
    public void setTableFieldFactory(TableFieldFactory fieldFactory) {
        this.fieldFactory = fieldFactory;

        // Assure visual refresh
        refreshRowCache();
    }

    /**
     * Gets the TableFieldFactory that is used to create editor for table cells.
     * 
     * The FieldFactory is only used if the CustomTable is editable.
     * 
     * @return TableFieldFactory used to create the Field instances.
     * @see #isEditable
     */
    public TableFieldFactory getTableFieldFactory() {
        return fieldFactory;
    }

    /**
     * Is table editable.
     * 
     * If table is editable a editor of type Field is created for each table
     * cell. The assigned FieldFactory is used to create the instances.
     * 
     * To provide custom editors for table cells create a class implementins the
     * FieldFactory interface, and assign it to table, and set the editable
     * property to true.
     * 
     * @return true if table is editable, false oterwise.
     * @see Field
     * @see fieldFactory
     * 
     */
    public boolean isEditable() {
        return editable;
    }

    /**
     * Sets the editable property.
     * 
     * If table is editable a editor of type Field is created for each table
     * cell. The assigned FieldFactory is used to create the instances.
     * 
     * To provide custom editors for table cells create a class implementins the
     * FieldFactory interface, and assign it to table, and set the editable
     * property to true.
     * 
     * @param editable
     *            true if table should be editable by user.
     * @see Field
     * @see fieldFactory
     * 
     */
    public void setEditable(boolean editable) {
        this.editable = editable;

        // Assure visual refresh
        refreshRowCache();
    }

    /** Sorts the table.
	 *
	 * @param propertyId
	 *            the property id
	 * @param ascending
	 *            the ascending
	 * @throws UnsupportedOperationException
	 *             if the container data source does not implement
	 *             Container.Sortable
	 * @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[],
	 *      boolean[])
	 */

    @Override
    public void sort(Object[] propertyId, boolean[] ascending)
            throws UnsupportedOperationException {
        final Container c = getContainerDataSource();
        if (c instanceof Container.Sortable) {
            final int pageIndex = getCurrentPageFirstItemIndex();
            boolean refreshingPreviouslyEnabled = disableContentRefreshing();
            ((Container.Sortable) c).sort(propertyId, ascending);
            setCurrentPageFirstItemIndex(pageIndex);
            if (refreshingPreviouslyEnabled) {
                enableContentRefreshing(true);
            }
            if (propertyId.length > 0 && ascending.length > 0) {
                // The first propertyId is the primary sorting criterion,
                // therefore the sort indicator should be there
                sortAscending = ascending[0];
                sortContainerPropertyId = propertyId[0];
            } else {
                sortAscending = true;
                sortContainerPropertyId = null;
            }
        } else if (c != null) {
            throw new UnsupportedOperationException(
                    "Underlying Data does not allow sorting");
        }
    }

    /**
     * Sorts the table by currently selected sorting column.
     * 
     * @throws UnsupportedOperationException
     *             if the container data source does not implement
     *             Container.Sortable
     */
    public void sort() {
        if (getSortContainerPropertyId() == null) {
            return;
        }
        sort(new Object[] { sortContainerPropertyId },
                new boolean[] { sortAscending });
    }

    /** Gets the container property IDs, which can be used to sort the item.
	 * <p>
	 * Note that the {@link #isSortEnabled()} state affects what this method
	 * returns. Disabling sorting causes this method to always return an empty
	 * collection.
	 *
	 * @return the sortable container property ids
	 * @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
	 */

    @Override
    public Collection<?> getSortableContainerPropertyIds() {
        final Container c = getContainerDataSource();
        if (c instanceof Container.Sortable && isSortEnabled()) {
            return ((Container.Sortable) c).getSortableContainerPropertyIds();
        }
        return Collections.EMPTY_LIST;
    }

    /**
     * Gets the currently sorted column property ID.
     * 
     * @return the Container property id of the currently sorted column.
     */
    public Object getSortContainerPropertyId() {
        return sortContainerPropertyId;
    }

    /**
     * Sets the currently sorted column property id.
     * 
     * @param propertyId
     *            the Container property id of the currently sorted column.
     */
    public void setSortContainerPropertyId(Object propertyId) {
        setSortContainerPropertyId(propertyId, true);
    }

    /** Internal method to set currently sorted column property id. With
	 * doSort flag actual sorting may be bypassed.
	 *
	 * @param propertyId
	 *            the property id
	 * @param doSort
	 *            the do sort
	 */
    private void setSortContainerPropertyId(Object propertyId, boolean doSort) {
        if ((sortContainerPropertyId != null && !sortContainerPropertyId
                .equals(propertyId))
                || (sortContainerPropertyId == null && propertyId != null)) {
            sortContainerPropertyId = propertyId;

            if (doSort) {
                sort();
                // Assures the visual refresh. This should not be necessary as
                // sort() calls refreshRowCache
                refreshRenderedCells();
            }
        }
    }

    /**
     * Is the table currently sorted in ascending order.
     * 
     * @return <code>true</code> if ascending, <code>false</code> if descending.
     */
    public boolean isSortAscending() {
        return sortAscending;
    }

    /**
     * Sets the table in ascending order.
     * 
     * @param ascending
     *            <code>true</code> if ascending, <code>false</code> if
     *            descending.
     */
    public void setSortAscending(boolean ascending) {
        setSortAscending(ascending, true);
    }

    /** Internal method to set sort ascending. With doSort flag actual sort
	 * can be bypassed.
	 *
	 * @param ascending
	 *            the ascending
	 * @param doSort
	 *            the do sort
	 */
    private void setSortAscending(boolean ascending, boolean doSort) {
        if (sortAscending != ascending) {
            sortAscending = ascending;
            if (doSort) {
                sort();
                // Assures the visual refresh. This should not be necessary as
                // sort() calls refreshRowCache
                refreshRenderedCells();
            }
        }
    }

    /**
     * Is sorting disabled altogether.
     * 
     * True iff no sortable columns are given even in the case where data source
     * would support this.
     * 
     * @return True iff sorting is disabled.
     * @deprecated As of 7.0, use {@link #isSortEnabled()} instead
     */
    @Deprecated
    public boolean isSortDisabled() {
        return !isSortEnabled();
    }

    /**
     * Checks if sorting is enabled.
     * 
     * @return true if sorting by the user is allowed, false otherwise
     */
    public boolean isSortEnabled() {
        return sortEnabled;
    }

    /**
     * Disables the sorting by the user altogether.
     * 
     * @param sortDisabled
     *            True iff sorting is disabled.
     * @deprecated As of 7.0, use {@link #setSortEnabled(boolean)} instead
     */
    @Deprecated
    public void setSortDisabled(boolean sortDisabled) {
        setSortEnabled(!sortDisabled);
    }

    /**
     * Enables or disables sorting.
     * <p>
     * Setting this to false disallows sorting by the user. It is still possible
     * to call {@link #sort()}.
     * 
     * 
     * @param sortEnabled
     *            true to allow the user to sort the table, false to disallow it
     */
    public void setSortEnabled(boolean sortEnabled) {
        if (this.sortEnabled != sortEnabled) {
            this.sortEnabled = sortEnabled;
            markAsDirty();
        }
    }

    /**
     * Used to create "generated columns"; columns that exist only in the
     * CustomTable, not in the underlying Container. Implement this interface
     * and pass it to CustomTable.addGeneratedColumn along with an id for the
     * column to be generated.
     * 
     */
    public interface ColumnGenerator extends Serializable {

        /**
         * Called by CustomTable when a cell in a generated column needs to be
         * generated.
         * 
         * @param source
         *            the source CustomTable
         * @param itemId
         *            the itemId (aka rowId) for the of the cell to be generated
         * @param columnId
         *            the id for the generated column (as specified in
         *            addGeneratedColumn)
         * @return A {@link Component} that should be rendered in the cell or a
         *         {@link String} that should be displayed in the cell. Other
         *         return values are not supported.
         */
        public abstract Object generateCell(CustomTable source, Object itemId,
                Object columnId);
    }

    /**
     * Set cell style generator for CustomTable.
     * 
     * @param cellStyleGenerator
     *            New cell style generator or null to remove generator.
     */
    public void setCellStyleGenerator(CellStyleGenerator cellStyleGenerator) {
        this.cellStyleGenerator = cellStyleGenerator;
        // Assures the visual refresh. No need to reset the page buffer
        // before as the content has not changed, only the style generators
        refreshRenderedCells();

    }

    /** Get the current cell style generator.
	 *
	 * @return the customTable cell specific style generator
	 */
    public CellStyleGenerator getCellStyleGenerator() {
        return cellStyleGenerator;
    }

    /**
     * Allow to define specific style on cells (and rows) contents. Implements
     * this interface and pass it to CustomTable.setCellStyleGenerator. Row
     * styles are generated when porpertyId is null. The CSS class name that
     * will be added to the cell content is
     * <tt>v-table-cell-content-[style name]</tt>, and the row style will be
     * <tt>v-table-row-[style name]</tt>.
     */
    public interface CellStyleGenerator extends Serializable {

        /**
         * Called by CustomTable when a cell (and row) is painted.
         * 
         * @param source
         *            the source CustomTable
         * @param itemId
         *            The itemId of the painted cell
         * @param propertyId
         *            The propertyId of the cell, null when getting row style
         * @return The style name to add to this cell or row. (the CSS class
         *         name will be v-table-cell-content-[style name], or
         *         v-table-row-[style name] for rows)
         */
        public abstract String getStyle(CustomTable source, Object itemId,
                Object propertyId);
    }

    /* (non-Javadoc)
     * @see com.vaadin.event.ItemClickEvent.ItemClickNotifier#addItemClickListener(com.vaadin.event.ItemClickEvent.ItemClickListener)
     */
    @Override
    public void addItemClickListener(ItemClickListener listener) {
        addListener(TableConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class,
                listener, ItemClickEvent.ITEM_CLICK_METHOD);
    }

    /** Adds the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #addItemClickListener(ItemClickListener)}
	 */
    @Override
    @Deprecated
    public void addListener(ItemClickListener listener) {
        addItemClickListener(listener);
    }

    /* (non-Javadoc)
     * @see com.vaadin.event.ItemClickEvent.ItemClickNotifier#removeItemClickListener(com.vaadin.event.ItemClickEvent.ItemClickListener)
     */
    @Override
    public void removeItemClickListener(ItemClickListener listener) {
        removeListener(TableConstants.ITEM_CLICK_EVENT_ID,
                ItemClickEvent.class, listener);
    }

    /** Removes the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #removeItemClickListener(ItemClickListener)}
	 */
    @Override
    @Deprecated
    public void removeListener(ItemClickListener listener) {
        removeItemClickListener(listener);
    }

    // Identical to AbstractCompoenentContainer.setEnabled();

    /* (non-Javadoc)
     * @see com.vaadin.ui.AbstractComponent#setEnabled(boolean)
     */
    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        if (getParent() != null && !getParent().isEnabled()) {
            // some ancestor still disabled, don't update children
            return;
        }
        markAsDirtyRecursive();
    }

    /** Sets the drag start mode of the CustomTable. Drag start mode controls
	 * how CustomTable behaves as a drag source.
	 *
	 * @param newDragMode
	 *            the new drag mode
	 */
    public void setDragMode(TableDragMode newDragMode) {
        dragMode = newDragMode;
        markAsDirty();
    }

    /** Gets the drag mode.
	 *
	 * @return the current start mode of the CustomTable. Drag start mode
	 *         controls how CustomTable behaves as a drag source.
	 */
    public TableDragMode getDragMode() {
        return dragMode;
    }

    /**
     * Concrete implementation of {@link DataBoundTransferable} for data
     * transferred from a table.
     * 
     * @see DataBoundTransferable
     * 
     * @since 6.3
     */
    public class TableTransferable extends DataBoundTransferable {

        /**
		 * 
		 */
		private static final long serialVersionUID = 8358368561148789905L;

		/** Instantiates a new table transferable.
		 *
		 * @param rawVariables
		 *            the raw variables
		 */
        protected TableTransferable(Map<String, Object> rawVariables) {
            super(CustomTable.this, rawVariables);
            Object object = rawVariables.get("itemId");
            if (object != null) {
                setData("itemId", itemIdMapper.get((String) object));
            }
            object = rawVariables.get("propertyId");
            if (object != null) {
                setData("propertyId", columnIdMap.get((String) object));
            }
        }

        /* (non-Javadoc)
         * @see com.vaadin.event.DataBoundTransferable#getItemId()
         */
        @Override
        public Object getItemId() {
            return getData("itemId");
        }

        /* (non-Javadoc)
         * @see com.vaadin.event.DataBoundTransferable#getPropertyId()
         */
        @Override
        public Object getPropertyId() {
            return getData("propertyId");
        }

        /* (non-Javadoc)
         * @see com.vaadin.event.TransferableImpl#getSourceComponent()
         */
        @Override
        public CustomTable getSourceComponent() {
            return (CustomTable) super.getSourceComponent();
        }

    }

    /* (non-Javadoc)
     * @see com.vaadin.event.dd.DragSource#getTransferable(java.util.Map)
     */
    @Override
    public TableTransferable getTransferable(Map<String, Object> rawVariables) {
        TableTransferable transferable = new TableTransferable(rawVariables);
        return transferable;
    }

    /* (non-Javadoc)
     * @see com.vaadin.event.dd.DropTarget#getDropHandler()
     */
    @Override
    public DropHandler getDropHandler() {
        return dropHandler;
    }

    /** Sets the drop handler.
	 *
	 * @param dropHandler
	 *            the new drop handler
	 */
    public void setDropHandler(DropHandler dropHandler) {
        this.dropHandler = dropHandler;
    }

    /* (non-Javadoc)
     * @see com.vaadin.event.dd.DropTarget#translateDropTargetDetails(java.util.Map)
     */
    @Override
    public AbstractSelectTargetDetails translateDropTargetDetails(
            Map<String, Object> clientVariables) {
        return new AbstractSelectTargetDetails(clientVariables);
    }

    /**
     * Sets the behavior of how the multi-select mode should behave when the
     * table is both selectable and in multi-select mode.
     * <p>
     * Note, that on some clients the mode may not be respected. E.g. on touch
     * based devices CTRL/SHIFT base selection method is invalid, so touch based
     * browsers always use the {@link MultiSelectMode#SIMPLE}.
     * 
     * @param mode
     *            The select mode of the table
     */
    public void setMultiSelectMode(MultiSelectMode mode) {
        multiSelectMode = mode;
        markAsDirty();
    }

    /**
     * Returns the select mode in which multi-select is used.
     * 
     * @return The multi select mode
     */
    public MultiSelectMode getMultiSelectMode() {
        return multiSelectMode;
    }

    /**
     * Lazy loading accept criterion for CustomTable. Accepted target rows are
     * loaded from server once per drag and drop operation. Developer must
     * override one method that decides on which rows the currently dragged data
     * can be dropped.
     * 
     * <p>
     * Initially pretty much no data is sent to client. On first required
     * criterion check (per drag request) the client side data structure is
     * initialized from server and no subsequent requests requests are needed
     * during that drag and drop operation.
     */
    public static abstract class TableDropCriterion extends ServerSideCriterion {

        /**
		 * 
		 */
		private static final long serialVersionUID = -4438203379086782747L;

		/** The table. */
        private CustomTable table;

        /** The allowed item ids. */
        private Set<Object> allowedItemIds;

        /*
         * (non-Javadoc)
         * 
         * @see
         * com.vaadin.event.dd.acceptcriteria.ServerSideCriterion#getIdentifier
         * ()
         */

        @Override
        protected String getIdentifier() {
            return TableDropCriterion.class.getCanonicalName();
        }

        /*
         * (non-Javadoc)
         * 
         * @see
         * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#accepts(com.vaadin
         * .event.dd.DragAndDropEvent)
         */
        @Override
        @SuppressWarnings("unchecked")
        public boolean accept(DragAndDropEvent dragEvent) {
            AbstractSelectTargetDetails dropTargetData = (AbstractSelectTargetDetails) dragEvent
                    .getTargetDetails();
            table = (CustomTable) dragEvent.getTargetDetails().getTarget();
            Collection<?> visibleItemIds = table.getVisibleItemIds();
            allowedItemIds = getAllowedItemIds(dragEvent, table,
                    (Collection<Object>) visibleItemIds);

            return allowedItemIds.contains(dropTargetData.getItemIdOver());
        }

        /*
         * (non-Javadoc)
         * 
         * @see
         * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#paintResponse(
         * com.vaadin.server.PaintTarget)
         */

        @Override
        public void paintResponse(PaintTarget target) throws PaintException {
            /*
             * send allowed nodes to client so subsequent requests can be
             * avoided
             */
            Object[] array = allowedItemIds.toArray();
            for (int i = 0; i < array.length; i++) {
                String key = table.itemIdMapper.key(array[i]);
                array[i] = key;
            }
            target.addAttribute("allowedIds", array);
        }

        /** Gets the allowed item ids.
		 *
		 * @param dragEvent
		 *            the drag event
		 * @param table
		 *            the table for which the allowed item identifiers are
		 *            defined
		 * @param visibleItemIds
		 *            the list of currently rendered item identifiers, accepted
		 *            item id's need to be detected only for these visible items
		 * @return the set of identifiers for items on which the dragEvent will
		 *         be accepted
		 */
        protected abstract Set<Object> getAllowedItemIds(
                DragAndDropEvent dragEvent, CustomTable table,
                Collection<Object> visibleItemIds);

    }

    /**
     * Click event fired when clicking on the CustomTable headers. The event
     * includes a reference the the CustomTable the event originated from, the
     * property id of the column which header was pressed and details about the
     * mouse event itself.
     */
    public static class HeaderClickEvent extends ClickEvent {
        
        /**
		 * 
		 */
		private static final long serialVersionUID = -3842793591293767381L;
		/** The Constant HEADER_CLICK_METHOD. */
        public static final Method HEADER_CLICK_METHOD;

        static {
            try {
                // Set the header click method
                HEADER_CLICK_METHOD = HeaderClickListener.class
                        .getDeclaredMethod("headerClick",
                                new Class[] { HeaderClickEvent.class });
            } catch (final java.lang.NoSuchMethodException e) {
                // This should never happen
                throw new java.lang.RuntimeException(e);
            }
        }

        /** The column property id. */
        // The property id of the column which header was pressed
        private final Object columnPropertyId;

        /** Instantiates a new header click event.
		 *
		 * @param source
		 *            the source
		 * @param propertyId
		 *            the property id
		 * @param details
		 *            the details
		 */
        public HeaderClickEvent(Component source, Object propertyId,
                MouseEventDetails details) {
            super(source, details);
            columnPropertyId = propertyId;
        }

        /** Gets the property id of the column which header was pressed.
		 *
		 * @return The column propety id
		 */
        public Object getPropertyId() {
            return columnPropertyId;
        }
    }

    /**
     * Click event fired when clicking on the CustomTable footers. The event
     * includes a reference the the CustomTable the event originated from, the
     * property id of the column which header was pressed and details about the
     * mouse event itself.
     */
    public static class FooterClickEvent extends ClickEvent {
        
        /**
		 * 
		 */
		private static final long serialVersionUID = -5958041789945758720L;
		/** The Constant FOOTER_CLICK_METHOD. */
        public static final Method FOOTER_CLICK_METHOD;

        static {
            try {
                // Set the header click method
                FOOTER_CLICK_METHOD = FooterClickListener.class
                        .getDeclaredMethod("footerClick",
                                new Class[] { FooterClickEvent.class });
            } catch (final java.lang.NoSuchMethodException e) {
                // This should never happen
                throw new java.lang.RuntimeException(e);
            }
        }

        /** The column property id. */
        // The property id of the column which header was pressed
        private final Object columnPropertyId;

        /** Constructor.
		 *
		 * @param source
		 *            The source of the component
		 * @param propertyId
		 *            The propertyId of the column
		 * @param details
		 *            The mouse details of the click
		 */
        public FooterClickEvent(Component source, Object propertyId,
                MouseEventDetails details) {
            super(source, details);
            columnPropertyId = propertyId;
        }

        /** Gets the property id of the column which header was pressed.
		 *
		 * @return The column propety id
		 */
        public Object getPropertyId() {
            return columnPropertyId;
        }
    }

    /** Interface for the listener for column header mouse click events. The
	 * headerClick method is called when the user presses a header column cell.
	 *
	 * @see HeaderClickEvent
	 */
    public interface HeaderClickListener extends Serializable {

        /** Called when a user clicks a header column cell.
		 *
		 * @param event
		 *            The event which contains information about the column and
		 *            the mouse click event
		 */
        public void headerClick(HeaderClickEvent event);
    }

    /** Interface for the listener for column footer mouse click events. The
	 * footerClick method is called when the user presses a footer column cell.
	 *
	 * @see FooterClickEvent
	 */
    public interface FooterClickListener extends Serializable {

        /** Called when a user clicks a footer column cell.
		 *
		 * @param event
		 *            The event which contains information about the column and
		 *            the mouse click event
		 */
        public void footerClick(FooterClickEvent event);
    }

    /**
     * Adds a header click listener which handles the click events when the user
     * clicks on a column header cell in the CustomTable.
     * <p>
     * The listener will receive events which contain information about which
     * column was clicked and some details about the mouse event.
     * 
     * 
     * @param listener
     *            The handler which should handle the header click events.
     */
    public void addHeaderClickListener(HeaderClickListener listener) {
        addListener(TableConstants.HEADER_CLICK_EVENT_ID,
                HeaderClickEvent.class, listener,
                HeaderClickEvent.HEADER_CLICK_METHOD);
    }

    /** Adds the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #addHeaderClickListener(HeaderClickListener)}
	 */
    @Deprecated
    public void addListener(HeaderClickListener listener) {
        addHeaderClickListener(listener);
    }

    /** Removes a header click listener.
	 *
	 * @param listener
	 *            The listener to remove.
	 */
    public void removeHeaderClickListener(HeaderClickListener listener) {
        removeListener(TableConstants.HEADER_CLICK_EVENT_ID,
                HeaderClickEvent.class, listener);
    }

    /** Removes the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #removeHeaderClickListener(HeaderClickListener)}
	 */
    @Deprecated
    public void removeListener(HeaderClickListener listener) {
        removeHeaderClickListener(listener);
    }

    /**
     * Adds a footer click listener which handles the click events when the user
     * clicks on a column footer cell in the CustomTable.
     * <p>
     * The listener will receive events which contain information about which
     * column was clicked and some details about the mouse event.
     * 
     * 
     * @param listener
     *            The handler which should handle the footer click events.
     */
    public void addFooterClickListener(FooterClickListener listener) {
        addListener(TableConstants.FOOTER_CLICK_EVENT_ID,
                FooterClickEvent.class, listener,
                FooterClickEvent.FOOTER_CLICK_METHOD);
    }

    /** Adds the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #addFooterClickListener(FooterClickListener)}
	 */
    @Deprecated
    public void addListener(FooterClickListener listener) {
        addFooterClickListener(listener);
    }

    /** Removes a footer click listener.
	 *
	 * @param listener
	 *            The listener to remove.
	 */
    public void removeFooterClickListener(FooterClickListener listener) {
        removeListener(TableConstants.FOOTER_CLICK_EVENT_ID,
                FooterClickEvent.class, listener);
    }

    /** Removes the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #removeFooterClickListener(FooterClickListener)}
	 */
    @Deprecated
    public void removeListener(FooterClickListener listener) {
        removeFooterClickListener(listener);
    }

    /** Gets the footer caption beneath the rows.
	 *
	 * @param propertyId
	 *            The propertyId of the column *
	 * @return The caption of the footer or NULL if not set
	 */
    public String getColumnFooter(Object propertyId) {
        return columnFooters.get(propertyId);
    }

    /**
     * Sets the column footer caption. The column footer caption is the text
     * displayed beneath the column if footers have been set visible.
     * 
     * @param propertyId
     *            The properyId of the column
     * 
     * @param footer
     *            The caption of the footer
     */
    public void setColumnFooter(Object propertyId, String footer) {
        if (footer == null) {
            columnFooters.remove(propertyId);
        } else {
            columnFooters.put(propertyId, footer);
        }

        markAsDirty();
    }

    /**
     * Sets the footer visible in the bottom of the table.
     * <p>
     * The footer can be used to add column related data like sums to the bottom
     * of the CustomTable using setColumnFooter(Object propertyId, String
     * footer).
     * 
     * 
     * @param visible
     *            Should the footer be visible
     */
    public void setFooterVisible(boolean visible) {
        if (visible != columnFootersVisible) {
            columnFootersVisible = visible;
            markAsDirty();
        }
    }

    /** Is the footer currently visible?.
	 *
	 * @return Returns true if visible else false
	 */
    public boolean isFooterVisible() {
        return columnFootersVisible;
    }

    /**
     * This event is fired when a column is resized. The event contains the
     * columns property id which was fired, the previous width of the column and
     * the width of the column after the resize.
     */
    public static class ColumnResizeEvent extends Component.Event {
        
        /**
		 * 
		 */
		private static final long serialVersionUID = -8407371352547584420L;

		/** The Constant COLUMN_RESIZE_METHOD. */
        public static final Method COLUMN_RESIZE_METHOD;

        static {
            try {
                COLUMN_RESIZE_METHOD = ColumnResizeListener.class
                        .getDeclaredMethod("columnResize",
                                new Class[] { ColumnResizeEvent.class });
            } catch (final java.lang.NoSuchMethodException e) {
                // This should never happen
                throw new java.lang.RuntimeException(e);
            }
        }

        /** The previous width. */
        private final int previousWidth;
        
        /** The current width. */
        private final int currentWidth;
        
        /** The column property id. */
        private final Object columnPropertyId;

        /** Constructor.
		 *
		 * @param source
		 *            The source of the event
		 * @param propertyId
		 *            The columns property id
		 * @param previous
		 *            The width in pixels of the column before the resize event
		 * @param current
		 *            The width in pixels of the column after the resize event
		 */
        public ColumnResizeEvent(Component source, Object propertyId,
                int previous, int current) {
            super(source);
            previousWidth = previous;
            currentWidth = current;
            columnPropertyId = propertyId;
        }

        /**
         * Get the column property id of the column that was resized.
         * 
         * @return The column property id
         */
        public Object getPropertyId() {
            return columnPropertyId;
        }

        /** Get the width in pixels of the column before the resize event.
		 *
		 * @return Width in pixels
		 */
        public int getPreviousWidth() {
            return previousWidth;
        }

        /** Get the width in pixels of the column after the resize event.
		 *
		 * @return Width in pixels
		 */
        public int getCurrentWidth() {
            return currentWidth;
        }
    }

    /** Interface for listening to column resize events.
	 *
	 * @see ColumnResizeEvent
	 */
    public interface ColumnResizeListener extends Serializable {

        /** This method is triggered when the column has been resized.
		 *
		 * @param event
		 *            The event which contains the column property id, the
		 *            previous width of the column and the current width of the
		 *            column
		 */
        public void columnResize(ColumnResizeEvent event);
    }

    /**
     * Adds a column resize listener to the CustomTable. A column resize
     * listener is called when a user resizes a columns width.
     * 
     * @param listener
     *            The listener to attach to the CustomTable
     */
    public void addColumnResizeListener(ColumnResizeListener listener) {
        addListener(TableConstants.COLUMN_RESIZE_EVENT_ID,
                ColumnResizeEvent.class, listener,
                ColumnResizeEvent.COLUMN_RESIZE_METHOD);
    }

    /** Adds the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #addColumnResizeListener(ColumnResizeListener)}
	 */
    @Deprecated
    public void addListener(ColumnResizeListener listener) {
        addColumnResizeListener(listener);
    }

    /**
     * Removes a column resize listener from the CustomTable.
     * 
     * @param listener
     *            The listener to remove
     */
    public void removeColumnResizeListener(ColumnResizeListener listener) {
        removeListener(TableConstants.COLUMN_RESIZE_EVENT_ID,
                ColumnResizeEvent.class, listener);
    }

    /** Removes the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #removeColumnResizeListener(ColumnResizeListener)}
	 */
    @Deprecated
    public void removeListener(ColumnResizeListener listener) {
        removeColumnResizeListener(listener);
    }

    /**
     * This event is fired when a columns are reordered by the end user user.
     */
    public static class ColumnReorderEvent extends Component.Event {
        
        /**
		 * 
		 */
		private static final long serialVersionUID = 7037717344987539459L;
		/** The Constant METHOD. */
        public static final Method METHOD;

        static {
            try {
                METHOD = ColumnReorderListener.class.getDeclaredMethod(
                        "columnReorder",
                        new Class[] { ColumnReorderEvent.class });
            } catch (final java.lang.NoSuchMethodException e) {
                // This should never happen
                throw new java.lang.RuntimeException(e);
            }
        }

        /** Constructor.
		 *
		 * @param source
		 *            The source of the event
		 */
        public ColumnReorderEvent(Component source) {
            super(source);
        }

    }

    /** Interface for listening to column reorder events.
	 *
	 * @see ColumnReorderEvent
	 */
    public interface ColumnReorderListener extends Serializable {

        /** This method is triggered when the column has been reordered.
		 *
		 * @param event
		 *            the event
		 */
        public void columnReorder(ColumnReorderEvent event);
    }

    /**
     * Adds a column reorder listener to the CustomTable. A column reorder
     * listener is called when a user reorders columns.
     * 
     * @param listener
     *            The listener to attach to the CustomTable
     */
    public void addColumnReorderListener(ColumnReorderListener listener) {
        addListener(TableConstants.COLUMN_REORDER_EVENT_ID,
                ColumnReorderEvent.class, listener, ColumnReorderEvent.METHOD);
    }

    /** Adds the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #addColumnReorderListener(ColumnReorderListener)}
	 */
    @Deprecated
    public void addListener(ColumnReorderListener listener) {
        addColumnReorderListener(listener);
    }

    /**
     * Removes a column reorder listener from the CustomTable.
     * 
     * @param listener
     *            The listener to remove
     */
    public void removeColumnReorderListener(ColumnReorderListener listener) {
        removeListener(TableConstants.COLUMN_REORDER_EVENT_ID,
                ColumnReorderEvent.class, listener);
    }

    /** Removes the listener.
	 *
	 * @param listener
	 *            the listener
	 * @deprecated As of 7.0, replaced by
	 *             {@link #removeColumnReorderListener(ColumnReorderListener)}
	 */
    @Deprecated
    public void removeListener(ColumnReorderListener listener) {
        removeColumnReorderListener(listener);
    }

    /** Set the item description generator which generates tooltips for cells
	 * and rows in the CustomTable.
	 *
	 * @param generator
	 *            The generator to use or null to disable
	 */
    public void setItemDescriptionGenerator(ItemDescriptionGenerator generator) {
        if (generator != itemDescriptionGenerator) {
            itemDescriptionGenerator = generator;
            // Assures the visual refresh. No need to reset the page buffer
            // before as the content has not changed, only the descriptions
            refreshRenderedCells();
        }
    }

    /** Get the item description generator which generates tooltips for cells
	 * and rows in the CustomTable.
	 *
	 * @return the customTable cell specific tooltip generator
	 */
    public ItemDescriptionGenerator getItemDescriptionGenerator() {
        return itemDescriptionGenerator;
    }

    /**
     * Row generators can be used to replace certain items in a table with a
     * generated string. The generator is called each time the table is
     * rendered, which means that new strings can be generated each time.
     * 
     * Row generators can be used for e.g. summary rows or grouping of items.
     */
    public interface RowGenerator extends Serializable {
        /**
         * Called for every row that is painted in the CustomTable. Returning a
         * GeneratedRow object will cause the row to be painted based on the
         * contents of the GeneratedRow. A generated row is by default styled
         * similarly to a header or footer row.
         * <p>
         * The GeneratedRow data object contains the text that should be
         * rendered in the row. The itemId in the container thus works only as a
         * placeholder.
         * <p>
         * If GeneratedRow.setSpanColumns(true) is used, there will be one
         * String spanning all columns (use setText("Spanning text")). Otherwise
         * you can define one String per visible column.
         * <p>
         * If GeneratedRow.setRenderAsHtml(true) is used, the strings can
         * contain HTML markup, otherwise all strings will be rendered as text
         * (the default).
         * <p>
         * A "v-table-generated-row" CSS class is added to all generated rows.
         * For custom styling of a generated row you can combine a RowGenerator
         * with a CellStyleGenerator.
         * <p>
         * 
         * @param table
         *            The CustomTable that is being painted
         * @param itemId
         *            The itemId for the row
         * @return A GeneratedRow describing how the row should be painted or
         *         null to paint the row with the contents from the container
         */
        public GeneratedRow generateRow(CustomTable table, Object itemId);
    }

    /** The Class GeneratedRow.
	 */
    public static class GeneratedRow implements Serializable {
        
        /**
		 * 
		 */
		private static final long serialVersionUID = -6224096809716484520L;

		/** The html content allowed. */
        private boolean htmlContentAllowed = false;
        
        /** The span columns. */
        private boolean spanColumns = false;
        
        /** The text. */
        private String[] text = null;

        /** Creates a new generated row. If only one string is passed in,
		 * columns are automatically spanned.
		 *
		 * @param text
		 *            the text
		 */
        public GeneratedRow(String... text) {
            setHtmlContentAllowed(false);
            setSpanColumns(text == null || text.length == 1);
            setText(text);
        }

        /** Pass one String if spanColumns is used, one String for each
		 * visible column otherwise.
		 *
		 * @param text
		 *            the new text
		 */
        public void setText(String... text) {
            if (text == null || (text.length == 1 && text[0] == null)) {
                text = new String[] { "" };
            }
            this.text = text;
        }

        /** Gets the text.
		 *
		 * @return the text
		 */
        protected String[] getText() {
            return text;
        }

        /** Gets the value.
		 *
		 * @return the value
		 */
        protected Object getValue() {
            return getText();
        }

        /** Checks if is html content allowed.
		 *
		 * @return true, if is html content allowed
		 */
        protected boolean isHtmlContentAllowed() {
            return htmlContentAllowed;
        }

        /** If set to true, all strings passed to {@link #setText(String...)}
		 * will be rendered as HTML.
		 *
		 * @param htmlContentAllowed
		 *            the new html content allowed
		 */
        public void setHtmlContentAllowed(boolean htmlContentAllowed) {
            this.htmlContentAllowed = htmlContentAllowed;
        }

        /** Checks if is span columns.
		 *
		 * @return true, if is span columns
		 */
        protected boolean isSpanColumns() {
            return spanColumns;
        }

        /** If set to true, only one string will be rendered, spanning the
		 * entire row.
		 *
		 * @param spanColumns
		 *            the new span columns
		 */
        public void setSpanColumns(boolean spanColumns) {
            this.spanColumns = spanColumns;
        }
    }

    /**
     * Assigns a row generator to the table. The row generator will be able to
     * replace rows in the table when it is rendered.
     * 
     * @param generator
     *            the new row generator
     */
    public void setRowGenerator(RowGenerator generator) {
        rowGenerator = generator;
        refreshRowCache();
    }

    /** Gets the row generator.
	 *
	 * @return the current row generator
	 */
    public RowGenerator getRowGenerator() {
        return rowGenerator;
    }

    /**
     * Sets a converter for a property id.
     * <p>
     * The converter is used to format the the data for the given property id
     * before displaying it in the table.
     * 
     * 
     * @param propertyId
     *            The propertyId to format using the converter
     * @param converter
     *            The converter to use for the property id
     */
    public void setConverter(Object propertyId, Converter<String, ?> converter) {
        if (!getContainerPropertyIds().contains(propertyId)) {
            throw new IllegalArgumentException("PropertyId " + propertyId
                    + " must be in the container");
        }

        if (!typeIsCompatible(converter.getModelType(), getType(propertyId))) {
            throw new IllegalArgumentException("Property type ("
                    + getType(propertyId)
                    + ") must match converter source type ("
                    + converter.getModelType() + ")");
        }
        propertyValueConverters.put(propertyId,
                (Converter<String, Object>) converter);
        refreshRowCache();
    }

    /**
     * Checks if there is a converter set explicitly for the given property id.
     * 
     * @param propertyId
     *            The propertyId to check
     * @return true if a converter has been set for the property id, false
     *         otherwise
     */
    protected boolean hasConverter(Object propertyId) {
        return propertyValueConverters.containsKey(propertyId);
    }

    /**
     * Returns the converter used to format the given propertyId.
     * 
     * @param propertyId
     *            The propertyId to check
     * @return The converter used to format the propertyId or null if no
     *         converter has been set
     */
    public Converter<String, Object> getConverter(Object propertyId) {
        return propertyValueConverters.get(propertyId);
    }

    /* (non-Javadoc)
     * @see com.vaadin.ui.AbstractComponent#setVisible(boolean)
     */
    @Override
    public void setVisible(boolean visible) {
        if (visible) {
            // We need to ensure that the rows are sent to the client when the
            // CustomTable is made visible if it has been rendered as invisible.
            setRowCacheInvalidated(true);
        }
        super.setVisible(visible);
    }

    /* (non-Javadoc)
     * @see com.vaadin.ui.HasComponents#iterator()
     */
    @Override
    public Iterator<Component> iterator() {
        if (visibleComponents == null) {
            Collection<Component> empty = Collections.emptyList();
            return empty.iterator();
        }
        return visibleComponents.iterator();
    }

    /** Gets the component iterator.
	 *
	 * @return the component iterator
	 * @deprecated As of 7.0, use {@link #iterator()} instead.
	 */
    @Deprecated
    public Iterator<Component> getComponentIterator() {
        return iterator();
    }

    /** Gets the logger.
	 *
	 * @return the logger
	 */
    private final Logger getLogger() {
        if (logger == null) {
            logger = Logger.getLogger(CustomTable.class.getName());
        }
        return logger;
    }
}
