/**
   * Helper that reads entries from legacy database and row-by-row creates new models and saves
   * them.
   *
   * @param context
   * @param legacyTable
   * @param propertyMap
   * @param model
   * @param dao
   */
  @SuppressWarnings("nls")
  private static final <TYPE extends AbstractModel> void upgradeTable(
      Context context,
      String legacyTable,
      HashMap<String, Property<?>> propertyMap,
      TYPE model,
      DatabaseDao<TYPE> dao) {

    if (!checkIfDatabaseExists(context, legacyTable)) return;

    SQLiteDatabase upgradeDb =
        new Astrid2UpgradeHelper(context, legacyTable, null, 1).getReadableDatabase();

    Cursor cursor = upgradeDb.rawQuery("SELECT * FROM " + legacyTable, null);
    UpgradeVisitorContainer<TYPE> container = new UpgradeVisitorContainer<TYPE>();
    container.cursor = cursor;
    container.model = model;
    ColumnUpgradeVisitor visitor = new ColumnUpgradeVisitor();
    for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
      model.clear();
      for (Entry<String, Property<?>> entry : propertyMap.entrySet()) {
        container.columnIndex = cursor.getColumnIndex(entry.getKey());
        entry.getValue().accept(visitor, container);
      }

      // special tweak for adding upgrade notes to tasks
      if (container.upgradeNotes != null) {
        if (container.model.getValue(Task.NOTES).length() == 0)
          container.model.setValue(Task.NOTES, container.upgradeNotes.toString());
        else {
          container.model.setValue(
              Task.NOTES, container.model.getValue(Task.NOTES) + "\n\n" + container.upgradeNotes);
        }
        container.upgradeNotes = null;
      }
      dao.createNew(container.model);
    }
    cursor.close();

    upgradeDb.close();
  }