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