@Override
    public Void visitLong(Property<Long> property, UpgradeVisitorContainer<?> data) {
      long value = data.cursor.getLong(data.columnIndex);

      // special handling for due date
      if (property == Task.DUE_DATE) {
        long preferredDueDate =
            data.cursor.getLong(data.cursor.getColumnIndex(LegacyTaskModel.PREFERRED_DUE_DATE));
        if (value == 0) value = preferredDueDate;
        else if (preferredDueDate != 0) {
          // had both absolute and preferred due dates. write
          // preferred due date into notes field
          if (data.upgradeNotes == null) data.upgradeNotes = new StringBuilder();
          data.upgradeNotes.append(
              "Goal Deadline: "
                  + DateUtilities.getDateString(
                      ContextManager.getContext(), new Date(preferredDueDate)));
        }
      } else if (property == Task.REMINDER_PERIOD) {
        // old period was stored in seconds
        value *= 1000L;
      } else if (property == Task.COMPLETION_DATE) {
        // check if the task was actually completed
        int progress =
            data.cursor.getInt(data.cursor.getColumnIndex(LegacyTaskModel.PROGRESS_PERCENTAGE));
        if (progress < 100) value = 0;
      }

      data.model.setValue(property, value);
      Log.d(
          "upgrade",
          "wrote " + value + " to -> " + property + " of model id " + data.cursor.getLong(1));
      return null;
    }
  /**
   * 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();
  }