// Insert a new model column at the specified index
  private void insertColumnBefore(DTColumnConfig modelColumn, int index, boolean bRedraw) {

    // Create new column for grid
    DynamicColumn<DTColumnConfig> column =
        new DynamicColumn<DTColumnConfig>(modelColumn, cellFactory.getCell(modelColumn), index);
    column.setVisible(!modelColumn.isHideColumn());
    DynamicColumn<DTColumnConfig> columnBefore = widget.getGridWidget().getColumns().get(index);

    // Create column data
    DynamicData data = widget.getGridWidget().getData();
    List<CellValue<? extends Comparable<?>>> columnData =
        new ArrayList<CellValue<? extends Comparable<?>>>();
    for (int iRow = 0; iRow < data.size(); iRow++) {
      DTCellValue dcv = new DTCellValue(modelColumn.getDefaultValue());
      CellValue<?> cell = cellValueFactory.makeCellValue(modelColumn, iRow, index, dcv);
      columnData.add(cell);
    }

    // Add column and data to grid
    widget.insertColumnBefore(columnBefore, column, columnData, bRedraw);
  }
  /**
   * Set the Decision Table's data. This removes all existing columns from the Decision Table and
   * re-creates them based upon the provided data.
   *
   * @param data
   */
  public void setModel(TypeSafeGuidedDecisionTable model) {
    if (model == null) {
      throw new IllegalArgumentException("model cannot be null");
    }

    this.model = model;
    this.cellFactory = new DecisionTableCellFactory(sce, widget.getGridWidget(), this.model);
    this.cellValueFactory = new DecisionTableCellValueFactory(sce, this.model);

    // Date converter is injected so a GWT compatible one can be used here and another in testing
    DecisionTableCellValueFactory.injectDateConvertor(GWTDateConverter.getInstance());

    // Setup command to recalculate System Controlled values when rows are added\deleted
    widget
        .getGridWidget()
        .getData()
        .setOnRowChangeCommand(
            new Command() {

              public void execute() {
                updateSystemControlledColumnValues();
              }
            });

    widget.getGridWidget().getData().clear();
    widget.getGridWidget().getColumns().clear();

    // Dummy rows because the underlying DecoratedGridWidget expects there
    // to be enough rows to receive the columns data
    final DynamicData data = widget.getGridWidget().getData();
    for (int iRow = 0; iRow < model.getData().size(); iRow++) {
      data.addRow();
    }

    // Static columns, Row#
    int colIndex = 0;
    DTColumnConfig colStatic;
    DynamicColumn<DTColumnConfig> columnStatic;
    colStatic = model.getRowNumberCol();
    columnStatic =
        new DynamicColumn<DTColumnConfig>(
            colStatic, cellFactory.getCell(colStatic), colIndex, true, false);
    columnStatic.setWidth(24);
    widget.appendColumn(columnStatic, makeColumnData(colStatic, colIndex++), false);

    // Static columns, Description
    colStatic = model.getDescriptionCol();
    columnStatic =
        new DynamicColumn<DTColumnConfig>(colStatic, cellFactory.getCell(colStatic), colIndex);
    widget.appendColumn(columnStatic, makeColumnData(colStatic, colIndex++), false);

    // Initialise CellTable's Metadata columns
    for (DTColumnConfig col : model.getMetadataCols()) {
      DynamicColumn<DTColumnConfig> column =
          new DynamicColumn<DTColumnConfig>(col, cellFactory.getCell(col), colIndex);
      column.setVisible(!col.isHideColumn());
      widget.appendColumn(column, makeColumnData(col, colIndex++), false);
    }

    // Initialise CellTable's Attribute columns
    for (DTColumnConfig col : model.getAttributeCols()) {
      DynamicColumn<DTColumnConfig> column =
          new DynamicColumn<DTColumnConfig>(col, cellFactory.getCell(col), colIndex);
      column.setVisible(!col.isHideColumn());
      column.setSystemControlled(col.isUseRowNumber());
      column.setSortable(!col.isUseRowNumber());
      widget.appendColumn(column, makeColumnData(col, colIndex++), false);
    }

    // Initialise CellTable's Condition columns
    assertConditionColumnGrouping(model);
    for (DTColumnConfig col : model.getConditionCols()) {
      DynamicColumn<DTColumnConfig> column =
          new DynamicColumn<DTColumnConfig>(col, cellFactory.getCell(col), colIndex);
      column.setVisible(!col.isHideColumn());
      widget.appendColumn(column, makeColumnData(col, colIndex++), false);
    }

    // Initialise CellTable's Action columns
    for (DTColumnConfig col : model.getActionCols()) {
      DynamicColumn<DTColumnConfig> column =
          new DynamicColumn<DTColumnConfig>(col, cellFactory.getCell(col), colIndex);
      column.setVisible(!col.isHideColumn());
      widget.appendColumn(column, makeColumnData(col, colIndex++), false);
    }

    // Ensure System Controlled values are correctly initialised
    updateSystemControlledColumnValues();

    // Draw header first as the size of child Elements depends upon it
    widget.getHeaderWidget().redraw();
    widget.getSidebarWidget().redraw();

    // Schedule redraw of grid after sizes of child Elements have been set
    Scheduler.get()
        .scheduleFinally(
            new ScheduledCommand() {

              public void execute() {
                widget.getGridWidget().redraw();
              }
            });
  }