Source code

KittyORM mig v.2 implementation sources**
  1. Click to view MigrationDBv2.class:
     1@KITTY_DATABASE(
     2        isLoggingOn = true,
     3        isProductionOn = false,
     4        databaseName = "mig",
     5        databaseVersion = 2,
     6        logTag = MigrationDBv2.LTAG,
     7        domainPackageNames = {"net.akaish.kittyormdemo.sqlite.migrations.migv2"}
     8)
     9@KITTY_DATABASE_REGISTRY(
    10        domainModels = {
    11                net.akaish.kittyormdemo.sqlite.migrations.migv2.MigOneModel.class,
    12                net.akaish.kittyormdemo.sqlite.migrations.migv2.MigTwoModel.class
    13        }
    14)
    15@KITTY_DATABASE_HELPER(
    16        onUpgradeBehavior = KITTY_DATABASE_HELPER.UpgradeBehavior.DROP_AND_CREATE
    17)
    18public class MigrationDBv2 extends KittyDatabase {
    19
    20    public static final String LTAG = "MIGv2";
    21
    22    /**
    23     * KittyORM main database class that represents bootstrap and holder for all related with database
    24     * components.
    25     *
    26     * @param ctx
    27     */
    28    public MigrationDBv2(Context ctx) {
    29        super(ctx);
    30    }
    31}

  2. Click to view MigOneModel.class:
     1@KITTY_TABLE(
     2        tableName = "mig_one"
     3)
     4public class MigOneModel extends KittyModel {
     5    @KITTY_COLUMN(
     6            columnOrder = 0,
     7            isIPK = true)
     8    public Long id;
     9
    10    @KITTY_COLUMN(columnOrder = 1)
    11    @NOT_NULL
    12    @DEFAULT(predefinedLiteralValue = LiteralValues.CURRENT_DATE)
    13    public String creationDate;
    14
    15    @KITTY_COLUMN(columnOrder = 2)
    16    @DEFAULT(signedInteger = 228)
    17    @ONE_COLUMN_INDEX(indexName = "m1_di_index")
    18    public Integer defaultInteger;
    19
    20    @KITTY_COLUMN(columnOrder = 3)
    21    public Timestamp currentTimestamp;
    22
    23    public String toString() {
    24        return new StringBuilder(64)
    25                .append("[ id = ")
    26                .append(id)
    27                .append(" ; creationDate = ")
    28                .append(creationDate)
    29                .append(" ; someInteger = ")
    30                .append(defaultInteger)
    31                .append(" ; currentTimestamp = ")
    32                .append(currentTimestamp)
    33                .append(" ]").toString();
    34    }
    35}

  3. Click to view MigTwoModel.class:
     1@KITTY_TABLE(
     2        tableName = "mig_two"
     3)
     4@INDEX(
     5        indexName = "m2_sa_index",
     6        indexColumns = {"some_animal"}
     7)
     8public class MigTwoModel extends KittyModel {
     9
    10    @KITTY_COLUMN(
    11            columnOrder = 0,
    12            isIPK = true
    13    )
    14    public Long id;
    15
    16    @KITTY_COLUMN(
    17            columnOrder = 1
    18    )
    19    @FOREIGN_KEY(
    20            reference = @FOREIGN_KEY_REFERENCE(
    21                    foreignTableName = "mig_one",
    22                    foreignTableColumns = {"id"},
    23                    onUpdate = OnUpdateDeleteActions.CASCADE,
    24                    onDelete = OnUpdateDeleteActions.CASCADE
    25            )
    26    )
    27    public Long migOneReference;
    28
    29    @KITTY_COLUMN(
    30            columnOrder = 2
    31    )
    32    public Animals someAnimal;
    33
    34    @Override
    35    public String toString() {
    36        return new StringBuilder(64)
    37                .append("[ id = ")
    38                .append(id)
    39                .append(" ; migOneReference = ")
    40                .append(migOneReference)
    41                .append(" ; someAnimal = ")
    42                .append(someAnimal)
    43                .append(" ] ").toString();
    44    }
    45}

Fragment and utility code used in this tutorial**
  1. Click to view MigV2RandomModelFactory.class:
     1public class MigV2RandomModelFactory {
     2    final Context ctx;
     3    final Random rnd;
     4
     5    public MigV2RandomModelFactory(Context ctx) {
     6        this.ctx = ctx;
     7        this.rnd = new Random();
     8    }
     9
    10    public MigOneModel newM1RndModel() {
    11        return newM1RndModel(rnd.nextBoolean());
    12    }
    13
    14    public MigOneModel newM1RndModel(boolean setCDDefault) {
    15        MigOneModel model = new MigOneModel();
    16        if(setCDDefault)
    17            model.setFieldExclusion("creationDate");
    18        else
    19            model.creationDate = new Date(System.currentTimeMillis()).toString();
    20        model.defaultInteger = rnd.nextInt();
    21        model.currentTimestamp = new Timestamp(System.currentTimeMillis());
    22        return model;
    23    }
    24
    25    public MigTwoModel newM2RndModel(ArrayList<MigOneModel> models) {
    26        int mlSize = models.size();
    27        return newM2RndModel(models.get(rnd.nextInt(mlSize)).id);
    28    }
    29
    30    public MigTwoModel newM2RndModel(Long migOneReference) {
    31        MigTwoModel model = new MigTwoModel();
    32        model.someAnimal = Animals.rndAnimal(rnd);
    33        model.migOneReference = migOneReference;
    34        return model;
    35    }
    36    
    37}

  2. Click to view Lesson5Tab2DCMigrations.class:
      1public class Lesson5Tab2DCMigrations extends Lesson5BaseFragment {
      2
      3    private MigrationDBv2 databaseV2;
      4    private SharedPreferencesMigDB sf;
      5
      6    private Button insertRandomButton;
      7    private Button clearTableButton;
      8    private Button deleteDatabaseButton;
      9
     10    private ListView eventsListView;
     11
     12    private TextView statusTV;
     13
     14    private MigDatabaseState mdbState;
     15
     16
     17    final static int DB_IMPLEMENTATION_VERSION = 2;
     18    final static int TABLE_AMOUNT = 2;
     19
     20    public Lesson5Tab2DCMigrations() {}
     21
     22    @Override
     23    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     24        View rootView = inflater.inflate(R.layout.lesson5_tab2_dc_migration, container, false);
     25
     26        insertRandomButton = rootView.findViewById(R.id.l5_t2_go_button);
     27        clearTableButton = rootView.findViewById(R.id.l5_t2_clear_button);
     28        deleteDatabaseButton = rootView.findViewById(R.id.l5_t2_delete_database_button);
     29
     30        eventsListView = rootView.findViewById(R.id.l5_t2_actions);
     31
     32        insertRandomButton.setOnClickListener(new View.OnClickListener() {
     33            @Override
     34            public void onClick(View v) {
     35                insert25RND();
     36            }
     37        });
     38
     39        clearTableButton.setOnClickListener(new View.OnClickListener() {
     40            @Override
     41            public void onClick(View v) {
     42                clearTable();
     43            }
     44        });
     45
     46        deleteDatabaseButton.setOnClickListener(new View.OnClickListener() {
     47            @Override
     48            public void onClick(View v) {
     49                deleteDatabase();
     50            }
     51        });
     52
     53        statusTV = rootView.findViewById(R.id.l5_t2_status);
     54
     55
     56        setUpExpandedList(
     57                rootView,
     58                R.id._l5_t2_expanded_panel_list,
     59                R.id._l5_t2_expanded_panel_text,
     60                R.string._l5_t2_expanded_text_pattern
     61        );
     62
     63        reloadTableExpandedList();
     64        reloadStatus();
     65        return rootView;
     66    }
     67
     68    public MigDatabaseState getMdbState(Context context, int implVersion, String[] tables) {
     69        if(mdbState != null) return mdbState;
     70        mdbState = new MigDatabaseState(implVersion, tables, context, getSf());
     71        return mdbState;
     72    }
     73
     74    public void reloadStatus() {
     75        if(statusTV != null) {
     76            statusTV.setText(getMdbState(getContext(), DB_IMPLEMENTATION_VERSION, new String[] {M1M1TN, M1M2TN}).toString());
     77        }
     78    }
     79
     80
     81    @Override
     82    public void onVisible() {
     83        reloadTableExpandedList();
     84        reloadStatus();
     85    }
     86
     87    private SharedPreferencesMigDB getSf() {
     88        if(sf != null) return sf;
     89        sf = new SharedPreferencesMigDB(getContext());
     90        return sf;
     91    }
     92
     93    private MigrationDBv2 getDatabase() {
     94        // retrieving existing database after upgrade -> downgrade would cause onUpgrade() script would be run after mapper fetching
     95        databaseV2 = new MigrationDBv2(getContext());
     96        return databaseV2;
     97    }
     98
     99    private void insert25RND() {
    100        new InsertRandomAsync().execute(0l);
    101    }
    102
    103    private void clearTable() {
    104        new WipeAsync().execute(0l);
    105    }
    106
    107    private void deleteDatabase() {
    108        new DeleteDatabaseAsync().execute(0l);
    109    }
    110
    111    private void reloadTableExpandedList() {
    112        new ReloadTableAsync().execute(0l);
    113    }
    114
    115    @Override
    116    protected int snackbarMessageResource() {
    117        return R.string._l5_t2_snackbar_message;
    118    }
    119
    120
    121
    122    // Asyncs
    123
    124    class ReloadTableAsync extends AsyncTask<Long, Long, List<String>> {
    125
    126        @Override
    127        protected List<String> doInBackground(Long... params) {
    128            LinkedList<String> toListView = new LinkedList<>();
    129            if(getSf().isDatabaseCreated() && !getSf().isDatabaseDeletedManually() && getSf().currentMigDBVersion() == DB_IMPLEMENTATION_VERSION) {
    130                KittyMapper mapper = getDatabase().getMapper(MigOneModel.class);
    131                List<MigOneModel> m1Models = mapper.findAll();
    132                mapper.close();
    133                KittyMapper mapperT2 = getDatabase().getMapper(MigTwoModel.class);
    134                List<MigTwoModel> m2Models = mapperT2.findAll();
    135                if(m1Models == null) {
    136                    toListView.addLast(format(getContext().getString(R.string._l5_t2_m1_db), 0));
    137                } else {
    138                    toListView.addLast(format(getContext().getString(R.string._l5_t2_m1_db), m1Models.size()));
    139                    Iterator<MigOneModel> mI = m1Models.iterator();
    140                    while (mI.hasNext()) {
    141                        toListView.addLast(mI.next().toString());
    142                    }
    143                }
    144                if(m2Models == null) {
    145                    toListView.addLast(format(getContext().getString(R.string._l5_t2_m2_db), 0));
    146                } else {
    147                    toListView.addLast(format(getContext().getString(R.string._l5_t2_m2_db), m2Models.size()));
    148                    Iterator<MigTwoModel> mI = m2Models.iterator();
    149                    while (mI.hasNext()) {
    150                        toListView.addLast(mI.next().toString());
    151                    }
    152                }
    153                return toListView;
    154            } else {
    155                if(!getSf().isDatabaseCreated() || getSf().isDatabaseDeletedManually()) {
    156                    toListView.addLast(getString(R.string._l5_t2_m1_db_doesnt_exist));
    157                    return toListView;
    158                } else {
    159                    toListView.addLast(format(getString(R.string._l5_t2_m1_db_has_different_version), getSf().currentMigDBVersion()));
    160                    return toListView;
    161                }
    162            }
    163        }
    164
    165        @Override
    166        protected void onPostExecute(List<String> result) {
    167            int tableAmount = TABLE_AMOUNT;
    168            if(getSf().isDatabaseDeletedManually() || !getSf().isDatabaseCreated() || getSf().currentMigDBVersion() != DB_IMPLEMENTATION_VERSION)
    169                tableAmount = 0;
    170            if(result != null) {
    171                events.setAdapter(new MigAdapter(getContext(), result));
    172                int recordsAmount = result.size() - TABLE_AMOUNT;
    173                if(tableAmount == 0)
    174                    recordsAmount = 0;
    175                expandedTitle.setText(format(expandeddTitlePattern, recordsAmount, tableAmount));
    176            } else {
    177                events.setAdapter(new MigAdapter(getContext(), new LinkedList<String>()));
    178                expandedTitle.setText(format(expandeddTitlePattern, 0, tableAmount));
    179            }
    180        }
    181    }
    182
    183    private static final String ERR_STRING_WIPE = "Lesson5tab2WipeDataError, see exception details!";
    184
    185    class WipeAsync extends AsyncTask<Long, Long, WipeAsyncResult> {
    186
    187        ProgressDialog dialog;
    188
    189        @Override
    190        protected void onPreExecute() {
    191            dialog = ProgressDialog.show(
    192                    getLessonActivity(),
    193                    getString(R.string._l5_t2_running_requested_operation_pg_title),
    194                    getString(R.string._l5_t2_running_requested_operation_pg_body)
    195            );
    196            dialog.setCancelable(false);
    197        }
    198
    199        @Override
    200        protected WipeAsyncResult doInBackground(Long... params) {
    201            if(getSf().isDatabaseCreated() && !getSf().isDatabaseDeletedManually() && getSf().currentMigDBVersion() == DB_IMPLEMENTATION_VERSION) {
    202                try {
    203                    KittyMapper mapper = getDatabase().getMapper(MigOneModel.class);
    204                    KittyMapper mapper2 = getDatabase().getMapper(MigTwoModel.class);
    205                    long recordsCount = mapper.countAll() + mapper2.countAll();
    206                    long affected = mapper.deleteAll() + mapper2.deleteAll();
    207                    mapper.close(); mapper2.close();
    208                    return new WipeAsyncResult(true, false, DB_IMPLEMENTATION_VERSION, affected, recordsCount);
    209                } catch (Exception e) {
    210                    Log.e(MigrationDBv2.LTAG, ERR_STRING_WIPE, e);
    211                    if (e instanceof KittyRuntimeException) {
    212                        if (((KittyRuntimeException) e).getNestedException() != null) {
    213                            Log.e(MigrationDBv2.LTAG, ERR_STRING_WIPE, ((KittyRuntimeException) e).getNestedException());
    214                        }
    215                    }
    216                    return new WipeAsyncResult(true, false, DB_IMPLEMENTATION_VERSION, -1l, -1l);
    217                }
    218            } else {
    219                return new WipeAsyncResult(
    220                        getSf().isDatabaseCreated(),
    221                        getSf().isDatabaseDeletedManually(),
    222                        getSf().currentMigDBVersion(),
    223                        -1l, -1l);
    224            }
    225        }
    226
    227        @Override
    228        protected void onPostExecute(WipeAsyncResult result) {
    229            dialog.cancel();
    230
    231            if (eventsListView != null) {
    232                eventsListView.setAdapter(new BasicArrayAdapter(getContext(), new LinkedList<String>()));
    233                eventsListView.setOnTouchListener(new View.OnTouchListener() {
    234
    235                    // Setting on Touch Listener for handling the touch inside ScrollView
    236                    @Override
    237                    public boolean onTouch(View v, MotionEvent event) {
    238                        // Disallow the touch request for parent scroll on touch of child view
    239                        v.getParent().requestDisallowInterceptTouchEvent(true);
    240                        return false;
    241                    }
    242                });
    243
    244                if(!result.isCreated) {
    245                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(getString(R.string._l5_op_not_existing));
    246                } else if (result.isDeleted) {
    247                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(getString(R.string._l5_op_deleted));
    248                } else if (result.dbVersion != DB_IMPLEMENTATION_VERSION) {
    249                    if(result.dbVersion < 1) {
    250                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_op_mig_version_is_lower), result.dbVersion, DB_IMPLEMENTATION_VERSION));
    251                    } else {
    252                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_op_mig_version_is_higher), result.dbVersion, DB_IMPLEMENTATION_VERSION));
    253                    }
    254                } else if (result.recordsCount > -1 && result.affectedRows > -1) {
    255                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_count_to_events), result.recordsCount));
    256                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_deleted_to_events), result.affectedRows));
    257                } else {
    258                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(getString(R.string._l5_t2_error_event));
    259                }
    260                ((BasicArrayAdapter) eventsListView.getAdapter()).notifyDataSetChanged();
    261                reloadTableExpandedList();
    262                reloadStatus();
    263            }
    264        }
    265    }
    266
    267    class WipeAsyncResult {
    268        boolean isCreated;
    269        boolean isDeleted;
    270        int dbVersion;
    271        Long affectedRows;
    272        Long recordsCount;
    273
    274        public WipeAsyncResult(boolean isCreated, boolean isDeleted, int dbVersion,
    275                               Long affectedRows, Long recordsCount) {
    276            this.isCreated = isCreated;
    277            this.isDeleted = isDeleted;
    278            this.dbVersion = dbVersion;
    279            this.affectedRows = affectedRows;
    280            this.recordsCount = recordsCount;
    281        }
    282    }
    283
    284    static final int INSERT_AMOUNT = 25;
    285    static final int INSERT_FK_AMOUNT = 10;
    286
    287    static final String ERR_INSERT_RND = "Lesson5tab2InsertRNDDataError, see exception details!";
    288
    289    class InsertRandomAsync extends AsyncTask<Long, Long, InsertRandomResults> {
    290        ProgressDialog dialog;
    291
    292        @Override
    293        protected void onPreExecute() {
    294            dialog = ProgressDialog.show(
    295                    getLessonActivity(),
    296                    getString(R.string._l5_t2_running_requested_operation_pg_title),
    297                    getString(R.string._l5_t2_running_requested_operation_pg_body)
    298            );
    299            dialog.setCancelable(false);
    300        }
    301
    302        @Override
    303        protected InsertRandomResults doInBackground(Long... strings) {
    304            if(getSf().currentMigDBVersion() > DB_IMPLEMENTATION_VERSION) {
    305                return new InsertRandomResults(
    306                        null,
    307                        null,
    308                        -1l,
    309                        -1l,
    310                        -1l,
    311                        false,
    312                        getSf().currentMigDBVersion()
    313                );
    314            } else {
    315                try {
    316                    KittyMapper mapper = getDatabase().getMapper(MigOneModel.class);
    317                    KittyMapper mapper2 = getDatabase().getMapper(MigTwoModel.class);
    318                    long recordsCount = mapper.countAll() + mapper2.countAll();
    319                    long affected = mapper.deleteAll() + mapper2.deleteAll();
    320                    LinkedList<MigOneModel> modelsToInsert = new LinkedList<>();
    321                    getSf().setDatabaseCreated(true);
    322                    getSf().setCurrentMigDBVersion(DB_IMPLEMENTATION_VERSION);
    323                    getSf().setDatabaseDeletedManually(false);
    324                    MigV2RandomModelFactory factory = new MigV2RandomModelFactory(getContext());
    325                    for (int i = 0; i < INSERT_AMOUNT; i++) {
    326                        MigOneModel m = factory.newM1RndModel();
    327                        modelsToInsert.addLast(m);
    328                    }
    329                    mapper.insertInTransaction(modelsToInsert);
    330                    List<MigOneModel> models = mapper.findAll();
    331
    332                    Iterator<MigOneModel> mI = models.iterator();
    333                    LinkedList<String> out = new LinkedList<>();
    334                    while (mI.hasNext()) {
    335                        out.addLast(mI.next().toString());
    336                    }
    337
    338                    LinkedList<MigTwoModel> models2ToInsert = new LinkedList<>();
    339                    for (int i = 0; i < INSERT_FK_AMOUNT; i++) {
    340                        MigTwoModel m = factory.newM2RndModel((ArrayList<MigOneModel>) models);
    341                        models2ToInsert.addLast(m);
    342                    }
    343                    mapper2.insertInTransaction(models2ToInsert);
    344                    List<MigTwoModel> models2 = mapper2.findAll();
    345
    346                    LinkedList<String> out2 = new LinkedList<>();
    347                    Iterator<MigTwoModel> mI2 = models2.iterator();
    348                    while (mI2.hasNext()) {
    349                        out2.addLast(mI2.next().toString());
    350                    }
    351
    352                    long recordsCountAfter = mapper.countAll() + mapper2.countAll();
    353                    mapper.close(); mapper2.close();
    354                    return new InsertRandomResults(out, out2, affected, recordsCount, recordsCountAfter, true, getSf().currentMigDBVersion());
    355                } catch (Exception e) {
    356                    Log.e(MigrationDBv1.LTAG, ERR_INSERT_RND, e);
    357                    if (e instanceof KittyRuntimeException) {
    358                        if (((KittyRuntimeException) e).getNestedException() != null) {
    359                            Log.e(MigrationDBv1.LTAG, ERR_INSERT_RND, ((KittyRuntimeException) e).getNestedException());
    360                        }
    361                    }
    362                    return new InsertRandomResults(
    363                            null,
    364                            null,
    365                            -1l,
    366                            -1l,
    367                            -1l,
    368                            false,
    369                            getSf().currentMigDBVersion()
    370                    );
    371                }
    372            }
    373        }
    374
    375        @Override
    376        protected void onPostExecute(InsertRandomResults result) {
    377            dialog.cancel();
    378            if (eventsListView != null) {
    379                eventsListView.setAdapter(new BasicArrayAdapter(getContext(), new LinkedList<String>()));
    380                eventsListView.setOnTouchListener(new View.OnTouchListener() {
    381
    382                    // Setting on Touch Listener for handling the touch inside ScrollView
    383                    @Override
    384                    public boolean onTouch(View v, MotionEvent event) {
    385                        // Disallow the touch request for parent scroll on touch of child view
    386                        v.getParent().requestDisallowInterceptTouchEvent(true);
    387                        return false;
    388                    }
    389                });
    390                if (result.operationSuccess) {
    391                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_count_to_events), result.modelsCountBefore));
    392                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_deleted_to_events), result.deletedModelsAffectedRows));
    393                    for (String modelString : result.modelInsertionsM1) {
    394                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_inserted_to_events), M1M1TN, modelString));
    395                    }
    396                    for (String modelString2 : result.modelInsertionsM2) {
    397                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_inserted_to_events), M1M2TN, modelString2));
    398                    }
    399                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_count_to_events), result.modelsCountAfter));
    400                } else {
    401                    if(getSf().currentMigDBVersion() > DB_IMPLEMENTATION_VERSION) {
    402                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_op_mig_version_is_higher), result.dbVersion, DB_IMPLEMENTATION_VERSION));
    403                    } else {
    404                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(getString(R.string._l5_t2_error_event));
    405                    }
    406                }
    407                ((BasicArrayAdapter) eventsListView.getAdapter()).notifyDataSetChanged();
    408                reloadTableExpandedList();
    409                reloadStatus();
    410            }
    411        }
    412
    413
    414    }
    415
    416    class InsertRandomResults {
    417        List<String> modelInsertionsM1;
    418        List<String> modelInsertionsM2;
    419        long deletedModelsAffectedRows;
    420        long modelsCountBefore;
    421        long modelsCountAfter;
    422        boolean operationSuccess;
    423        int dbVersion;
    424
    425        public InsertRandomResults(List<String> modelInsertionsM1, List<String> modelInsertionsM2,
    426                                   long deletedModelsAffectedRows,
    427                                   long modelsCountBefore, long modelsCountAfter, boolean opSuccess,
    428                                   int dbVersion) {
    429            this.modelInsertionsM1 = modelInsertionsM1;
    430            this.modelInsertionsM2 = modelInsertionsM2;
    431            this.deletedModelsAffectedRows = deletedModelsAffectedRows;
    432            this.modelsCountBefore = modelsCountBefore;
    433            this.modelsCountAfter = modelsCountAfter;
    434            this.operationSuccess = opSuccess;
    435            this.dbVersion = dbVersion;
    436        }
    437    }
    438
    439    static final String ERR_DELETION = "Lesson5tab2DBDeleteError, see exception details!";
    440
    441    class DeleteDatabaseAsync extends AsyncTask<Long, Long, Integer> {
    442        ProgressDialog dialog;
    443
    444        final int DELETED = 1;
    445        final int NOT_DELETED = 2;
    446        final int ERROR = 3;
    447
    448        @Override
    449        protected void onPreExecute() {
    450            dialog = ProgressDialog.show(
    451                    getLessonActivity(),
    452                    getString(R.string._l5_t2_running_requested_operation_pg_title),
    453                    getString(R.string._l5_t2_running_requested_operation_pg_body)
    454            );
    455            dialog.setCancelable(false);
    456        }
    457
    458        @Override
    459        protected Integer doInBackground(Long... strings) {
    460            try {
    461                boolean deleted = getDatabase().deleteDatabase();
    462                getSf().setDatabaseDeletedManually(true);
    463                getSf().setDatabaseCreated(false);
    464                getSf().setCurrentMigDBVersion(-1);
    465                if(deleted)
    466                    return DELETED;
    467                else
    468                    return NOT_DELETED;
    469            } catch (Exception e) {
    470                Log.e(MigrationDBv2.LTAG, ERR_DELETION, e);
    471                if (e instanceof KittyRuntimeException) {
    472                    if (((KittyRuntimeException) e).getNestedException() != null) {
    473                        Log.e(MigrationDBv2.LTAG, ERR_DELETION, ((KittyRuntimeException) e).getNestedException());
    474                    }
    475                }
    476                return ERROR;
    477            }
    478        }
    479
    480        @Override
    481        protected void onPostExecute(Integer result) {
    482            dialog.cancel();
    483            if (eventsListView != null) {
    484                eventsListView.setAdapter(new BasicArrayAdapter(getContext(), new LinkedList<String>()));
    485                eventsListView.setOnTouchListener(new View.OnTouchListener() {
    486
    487                    // Setting on Touch Listener for handling the touch inside ScrollView
    488                    @Override
    489                    public boolean onTouch(View v, MotionEvent event) {
    490                        // Disallow the touch request for parent scroll on touch of child view
    491                        v.getParent().requestDisallowInterceptTouchEvent(true);
    492                        return false;
    493                    }
    494                });
    495                switch (result) {
    496                    case DELETED:
    497                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_delete_db_success)));
    498                        break;
    499                    case NOT_DELETED:
    500                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_delete_db_fail)));
    501                        break;
    502                    case ERROR:
    503                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l5_t2_error_event)));
    504                        break;
    505                }
    506                ((BasicArrayAdapter) eventsListView.getAdapter()).notifyDataSetChanged();
    507                reloadTableExpandedList();
    508                reloadStatus();
    509            }
    510        }
    511    }
    512
    513    // Expanded list
    514    MigAdapter migAdapter;
    515
    516    @Override
    517    protected void setUpExpandedList(View rootView, int eventsId, int eventsTitleId, int eventTitleStringPattern) {
    518        events = (ListView) rootView.findViewById(eventsId);
    519        expandedTitle = (TextView) rootView.findViewById(eventsTitleId);
    520        expandeddTitlePattern = getString(eventTitleStringPattern);
    521
    522        expandedTitle.setText(format(expandeddTitlePattern, 0));
    523
    524        if(expandedAdapter == null) {
    525            migAdapter = new MigAdapter(getContext(), new LinkedList<String>());
    526        }
    527
    528        events.setAdapter(migAdapter);
    529        events.setOnTouchListener(new View.OnTouchListener() {
    530
    531            // Setting on Touch Listener for handling the touch inside ScrollView
    532            @Override
    533            public boolean onTouch(View v, MotionEvent event) {
    534                // Disallow the touch request for parent scroll on touch of child view
    535                v.getParent().requestDisallowInterceptTouchEvent(true);
    536                return false;
    537            }
    538        });
    539    }
    540
    541    // Fab menu section
    542
    543    @Override
    544    public View.OnClickListener helpFabMenuAction() {
    545        return new View.OnClickListener() {
    546
    547            /**
    548             * Called when a view has been clicked.
    549             *
    550             * @param v The view that was clicked.
    551             */
    552            @Override
    553            public void onClick(View v) {
    554                ((KittyTutorialActivity) getParentFragment().getActivity()).showWebViewDialog(L5_T2_TUTORIAL);
    555            }
    556        };
    557    }
    558
    559    @Override
    560    public View.OnClickListener sourceFabMenuAction() {
    561        return new View.OnClickListener() {
    562
    563            /**
    564             * Called when a view has been clicked.
    565             *
    566             * @param v The view that was clicked.
    567             */
    568            @Override
    569            public void onClick(View v) {
    570                ((KittyTutorialActivity) getParentFragment().getActivity()).showWebViewDialog(L5_T2_SOURCE);
    571            }
    572        };
    573    }
    574
    575    @Override
    576    public View.OnClickListener schemaFabMenuAction() {
    577        return new View.OnClickListener() {
    578
    579            /**
    580             * Called when a view has been clicked.
    581             *
    582             * @param v The view that was clicked.
    583             */
    584            @Override
    585            public void onClick(View v) {
    586                ((KittyTutorialActivity) getParentFragment().getActivity()).showWebViewDialog(L5_T2_SCHEMA);
    587            }
    588        };
    589    }
    590}