void removeGroupByColumn(ColumnDefinition cd) {
   try {
     TableUtil.get()
         .atomicRemoveGroupByColumn(
             Tables.getInstance(), getAppName(), getTableId(), cd.getElementKey());
   } catch (ServicesAvailabilityException e) {
     Toast.makeText(getActivity(), "Unable to remove column from Group By list", Toast.LENGTH_LONG)
         .show();
   }
 }
 void setColumnAsIndexedCol(ColumnDefinition cd) {
   try {
     TableUtil.get()
         .atomicSetIndexColumn(
             Tables.getInstance(),
             getAppName(),
             getTableId(),
             (cd == null) ? null : cd.getElementKey());
   } catch (ServicesAvailabilityException e) {
     Toast.makeText(getActivity(), "Unable to set Index Column", Toast.LENGTH_LONG).show();
   }
 }
  @Override
  public void prepHeaderCellOccm(ContextMenu menu, CellInfo cellInfo)
      throws ServicesAvailabilityException {
    this.mLastHeaderCellMenued = cellInfo;

    String sortColumn;
    String indexColumn;
    ArrayList<String> groupByColumns;
    DbHandle db = null;
    try {
      db = Tables.getInstance().getDatabase().openDatabase(getAppName());
      sortColumn =
          TableUtil.get().getSortColumn(Tables.getInstance(), getAppName(), db, getTableId());
      indexColumn =
          TableUtil.get().getIndexColumn(Tables.getInstance(), getAppName(), db, getTableId());
      groupByColumns =
          TableUtil.get()
              .getColumnOrder(
                  Tables.getInstance(),
                  getAppName(),
                  db,
                  getTableId(),
                  spreadsheetTable.getColumnDefinitions());
    } finally {
      if (db != null) {
        Tables.getInstance().getDatabase().closeDatabase(getAppName(), db);
      }
    }

    ColumnDefinition cd = spreadsheetTable.getColumnByElementKey(cellInfo.elementKey);
    if (groupByColumns.contains(cd.getElementKey())) {
      menu.add(
          ContextMenu.NONE,
          MENU_ITEM_ID_UNSET_COLUMN_AS_GROUP_BY,
          ContextMenu.NONE,
          "Unset as Group By");
    } else if ((sortColumn != null) && cellInfo.elementKey.equals(sortColumn)) {
      menu.add(
          ContextMenu.NONE, MENU_ITEM_ID_UNSET_COLUMN_AS_SORT, ContextMenu.NONE, "Unset as Sort");
    } else {
      menu.add(
          ContextMenu.NONE,
          MENU_ITEM_ID_SET_COLUMN_AS_GROUP_BY,
          ContextMenu.NONE,
          "Set as Group By");
      menu.add(ContextMenu.NONE, MENU_ITEM_ID_SET_COLUMN_AS_SORT, ContextMenu.NONE, "Set as Sort");
    }
    if (cellInfo.elementKey.equals(indexColumn)) {
      menu.add(
          ContextMenu.NONE, MENU_ITEM_ID_UNSET_AS_INDEXED_COL, ContextMenu.NONE, "Unfreeze Column");
    } else {
      menu.add(
          ContextMenu.NONE, MENU_ITEM_ID_SET_AS_INDEXED_COL, ContextMenu.NONE, "Freeze Column");
    }

    menu.add(
        ContextMenu.NONE,
        MENU_ITEM_ID_EDIT_COLUMN_COLOR_RULES,
        ContextMenu.NONE,
        getString(R.string.edit_column_color_rules));
  }
  @Override
  public void prepDataCellOccm(ContextMenu menu, CellInfo cellInfo)
      throws ServicesAvailabilityException {
    this.mLastDataCellMenued = cellInfo;
    ColumnDefinition cd = spreadsheetTable.getColumnByElementKey(cellInfo.elementKey);
    String localizedDisplayName;
    DbHandle db = null;
    try {
      db = Tables.getInstance().getDatabase().openDatabase(getAppName());
      localizedDisplayName =
          ColumnUtil.get()
              .getLocalizedDisplayName(
                  Tables.getInstance(), getAppName(), db, getTableId(), cd.getElementKey());
    } finally {
      if (db != null) {
        Tables.getInstance().getDatabase().closeDatabase(getAppName(), db);
      }
    }

    menu.setHeaderTitle(localizedDisplayName);

    MenuItem mi;
    if (this.hasGroupBys()) {
      mi = menu.add(ContextMenu.NONE, MENU_ITEM_ID_HISTORY_IN, ContextMenu.NONE, "View Collection");
      mi.setIcon(R.drawable.ic_view_headline_black_24dp);
    }
    // TODO: display value and use edit icon...
    //    mi = menu.add(ContextMenu.NONE, MENU_ITEM_ID_EDIT_CELL, ContextMenu.NONE,
    //        getString(R.string.edit_cell, viewString));
    //    mi.setIcon(R.drawable.ic_action_edit);

    String access =
        spreadsheetTable
            .getRowAtIndex(cellInfo.rowId)
            .getDataByKey(DataTableColumns.EFFECTIVE_ACCESS);

    if (access.contains("d")) {
      mi =
          menu.add(
              ContextMenu.NONE,
              MENU_ITEM_ID_DELETE_ROW,
              ContextMenu.NONE,
              getString(R.string.delete_row));
      mi.setIcon(R.drawable.ic_action_content_discard);
    }
    if (access.contains("w")) {
      mi =
          menu.add(
              ContextMenu.NONE,
              MENU_ITEM_ID_EDIT_ROW,
              ContextMenu.NONE,
              getString(R.string.edit_row));
      mi.setIcon(R.drawable.ic_mode_edit_black_24dp);
    }

    // check a join association with this column; add a join... option if
    // it is applicable.
    ArrayList<JoinColumn> joinColumns;
    db = null;
    try {
      db = Tables.getInstance().getDatabase().openDatabase(getAppName());
      joinColumns =
          ColumnUtil.get()
              .getJoins(Tables.getInstance(), getAppName(), db, getTableId(), cd.getElementKey());
    } finally {
      if (db != null) {
        Tables.getInstance().getDatabase().closeDatabase(getAppName(), db);
      }
    }

    if (joinColumns != null && joinColumns.size() != 0) {
      mi =
          menu.add(
              ContextMenu.NONE,
              MENU_ITEM_ID_OPEN_JOIN_TABLE,
              ContextMenu.NONE,
              getString(R.string.open_join_table));
      mi.setIcon(R.drawable.ic_search_black_24dp);
    }
  }
  @Override
  public boolean onContextItemSelected(MenuItem item) {
    SpreadsheetCell cell;
    TableDisplayActivity activity = (TableDisplayActivity) getActivity();

    switch (item.getItemId()) {
      case MENU_ITEM_ID_HISTORY_IN:
        cell = spreadsheetTable.getSpreadsheetCell(activity, this.mLastDataCellMenued);
        openCollectionView(cell);
        return true;
        //    case MENU_ITEM_ID_EDIT_CELL:
        //      cell = spreadsheetTable.getSpreadsheetCell(activity, this.mLastDataCellMenued);
        //      openCellEditDialog(cell);
        //      return true;
      case MENU_ITEM_ID_DELETE_ROW:
        cell = spreadsheetTable.getSpreadsheetCell(activity, this.mLastDataCellMenued);
        AlertDialog confirmDeleteAlert;
        // Prompt an alert box
        final String rowId = cell.row.getDataByKey(DataTableColumns.ID);
        AlertDialog.Builder alert = new AlertDialog.Builder(activity);
        alert
            .setTitle(getString(R.string.confirm_delete_row))
            .setMessage(getString(R.string.are_you_sure_delete_row, rowId));
        // OK Action => delete the row
        alert.setPositiveButton(
            getString(R.string.ok),
            new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int whichButton) {
                TableDisplayActivity activity = (TableDisplayActivity) getActivity();
                try {
                  deleteRow(rowId);
                  init();
                } catch (ActionNotAuthorizedException e) {
                  WebLogger.getLogger(activity.getAppName()).printStackTrace(e);
                  WebLogger.getLogger(activity.getAppName())
                      .e(TAG, "Not authorized for action while " + "accessing database");
                  Toast.makeText(
                          activity,
                          "Not authorized for action while accessing database",
                          Toast.LENGTH_LONG)
                      .show();
                } catch (ServicesAvailabilityException e) {
                  WebLogger.getLogger(activity.getAppName()).printStackTrace(e);
                  WebLogger.getLogger(activity.getAppName())
                      .e(TAG, "Error while accessing database");
                  Toast.makeText(activity, "Error while accessing database", Toast.LENGTH_LONG)
                      .show();
                }
              }
            });

        // Cancel Action
        alert.setNegativeButton(
            getString(R.string.cancel),
            new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int whichButton) {
                // Canceled.
              }
            });
        // show the dialog
        confirmDeleteAlert = alert.create();
        confirmDeleteAlert.show();
        return true;
      case MENU_ITEM_ID_EDIT_ROW:
        cell = spreadsheetTable.getSpreadsheetCell(activity, this.mLastDataCellMenued);
        // It is possible that a custom form has been defined for this table.
        // We will get the strings we need, and then set the parameter object.
        try {
          ActivityUtil.editRow(
              activity,
              activity.getAppName(),
              activity.getTableId(),
              activity.getColumnDefinitions(),
              cell.row);
        } catch (ServicesAvailabilityException e) {
          WebLogger.getLogger(activity.getAppName()).printStackTrace(e);
          WebLogger.getLogger(activity.getAppName()).e(TAG, "Error while accessing database");
          Toast.makeText(activity, "Error while accessing database", Toast.LENGTH_LONG).show();
          return true;
        }
        // launch ODK Collect
        return true;
      case MENU_ITEM_ID_OPEN_JOIN_TABLE:
        cell = spreadsheetTable.getSpreadsheetCell(getActivity(), this.mLastDataCellMenued);
        ColumnDefinition cd = spreadsheetTable.getColumnByElementKey(cell.elementKey);
        // Get the JoinColumn.
        ArrayList<JoinColumn> joinColumns;
        DbHandle db = null;
        try {
          db = Tables.getInstance().getDatabase().openDatabase(getAppName());
          joinColumns =
              ColumnUtil.get()
                  .getJoins(
                      Tables.getInstance(), getAppName(), db, getTableId(), cd.getElementKey());
        } catch (ServicesAvailabilityException e) {
          WebLogger.getLogger(activity.getAppName()).printStackTrace(e);
          WebLogger.getLogger(activity.getAppName()).e(TAG, "Error while accessing database");
          Toast.makeText(activity, "Error while accessing database", Toast.LENGTH_LONG).show();
          return true;
        } finally {
          if (db != null) {
            try {
              Tables.getInstance().getDatabase().closeDatabase(getAppName(), db);
            } catch (ServicesAvailabilityException e) {
              WebLogger.getLogger(activity.getAppName()).printStackTrace(e);
              WebLogger.getLogger(activity.getAppName()).e(TAG, "Error closing database");
              Toast.makeText(activity, "Error closing database", Toast.LENGTH_LONG).show();
            }
          }
        }

        AlertDialog.Builder badJoinDialog;
        // TODO should check for valid table properties and
        // column properties here. or rather valid ids and keys.
        if (joinColumns == null || joinColumns.size() == 0) {
          badJoinDialog = new AlertDialog.Builder(this.getActivity());
          badJoinDialog.setTitle("Bad Join");
          badJoinDialog.setMessage("A join column has not been " + "set in Column Properties.");
          badJoinDialog.create().show();
          WebLogger.getLogger(getAppName())
              .e(
                  TAG,
                  "cp.getJoins was null but open join table "
                      + "was requested for cp: "
                      + cd.getElementKey());
        } else if (joinColumns.size() != 1) {
          badJoinDialog = new AlertDialog.Builder(this.getActivity());
          badJoinDialog.setTitle("Bad Join");
          badJoinDialog.setMessage(
              "Multiple join associations have been " + "set in Column Properties.");
          badJoinDialog.create().show();
          WebLogger.getLogger(getAppName())
              .e(
                  TAG,
                  "cp.getJoins has multiple joins "
                      + "(missing code is needed to handle this) for cp: "
                      + cd.getElementKey());
        } else {
          JoinColumn joinColumn = joinColumns.get(0);
          if (joinColumn.getTableId().equals(JoinColumn.DEFAULT_NOT_SET_VALUE)
              || joinColumn.getElementKey().equals(JoinColumn.DEFAULT_NOT_SET_VALUE)) {
            badJoinDialog = new AlertDialog.Builder(this.getActivity());
            badJoinDialog.setTitle("Bad Join");
            badJoinDialog.setMessage("Both a table and column " + "must be set.");
            badJoinDialog.create().show();
            WebLogger.getLogger(getAppName())
                .e(
                    TAG,
                    "Bad elementKey or tableId in open join "
                        + "table. tableId: "
                        + joinColumn.getTableId()
                        + " elementKey: "
                        + joinColumn.getElementKey());
          } else {
            String tableId = joinColumn.getTableId();
            String elementKey = joinColumn.getElementKey();
            String joinedColTableDisplayName;
            db = null;
            try {
              db = Tables.getInstance().getDatabase().openDatabase(getAppName());
              joinedColTableDisplayName =
                  ColumnUtil.get()
                      .getLocalizedDisplayName(
                          Tables.getInstance(), getAppName(), db, tableId, elementKey);
            } catch (ServicesAvailabilityException e) {
              WebLogger.getLogger(activity.getAppName()).printStackTrace(e);
              WebLogger.getLogger(activity.getAppName()).e(TAG, "Error while accessing database");
              Toast.makeText(activity, "Error while accessing database", Toast.LENGTH_LONG).show();
            } finally {
              if (db != null) {
                try {
                  Tables.getInstance().getDatabase().closeDatabase(getAppName(), db);
                } catch (ServicesAvailabilityException e) {
                  WebLogger.getLogger(activity.getAppName()).printStackTrace(e);
                  WebLogger.getLogger(activity.getAppName()).e(TAG, "Error closing database");
                  Toast.makeText(activity, "Error closing database", Toast.LENGTH_LONG).show();
                }
              }
            }

            // I would prefer this kind of query to be set in another
            // object, but alas, it looks like atm it is hardcoded.
            Intent intent = new Intent(this.getActivity(), TableDisplayActivity.class);
            Bundle extras = new Bundle();
            IntentUtil.addAppNameToBundle(extras, getAppName());
            // TODO: pass the correct view type.
            IntentUtil.addFragmentViewTypeToBundle(extras, ViewFragmentType.SPREADSHEET);
            intent.putExtras(extras);
            getActivity().startActivityForResult(intent, Constants.RequestCodes.LAUNCH_VIEW);
            // Controller.launchTableActivity(context, joinedTable,
            // joinedTable.getDefaultViewType());
          }
        }
        return true;
      case MENU_ITEM_ID_SET_COLUMN_AS_GROUP_BY:
        addGroupByColumn(
            spreadsheetTable.getColumnByElementKey(this.mLastHeaderCellMenued.elementKey));
        init();
        return true;
      case MENU_ITEM_ID_UNSET_COLUMN_AS_GROUP_BY:
        removeGroupByColumn(
            spreadsheetTable.getColumnByElementKey(this.mLastHeaderCellMenued.elementKey));
        init();
        return true;
      case MENU_ITEM_ID_SET_COLUMN_AS_SORT:
        setColumnAsSort(
            spreadsheetTable.getColumnByElementKey(this.mLastHeaderCellMenued.elementKey));
        init();
        return true;
      case MENU_ITEM_ID_UNSET_COLUMN_AS_SORT:
        setColumnAsSort(null);
        init();
        return true;
      case MENU_ITEM_ID_SET_AS_INDEXED_COL:
        setColumnAsIndexedCol(
            spreadsheetTable.getColumnByElementKey(this.mLastHeaderCellMenued.elementKey));
        init();
        return true;
      case MENU_ITEM_ID_UNSET_AS_INDEXED_COL:
        setColumnAsIndexedCol(null);
        init();
        return true;
      case MENU_ITEM_ID_EDIT_COLUMN_COLOR_RULES:
        String elementKey = this.mLastHeaderCellMenued.elementKey;
        ActivityUtil.launchTablePreferenceActivityToEditColumnColorRules(
            this.getActivity(), getAppName(), getTableId(), elementKey);
      default:
        WebLogger.getLogger(getAppName())
            .e(TAG, "unrecognized menu item selected: " + item.getItemId());
        return super.onContextItemSelected(item);
    }
  }