Skip to content

Commit 19c0ec8

Browse files
committed
display import/export exceptions, even on preview
Prevents silent fail during import/export or preview when an exception arises. Signed-off-by: Aron Heinecke <aron.heinecke@t-online.de>
1 parent aa8bc57 commit 19c0ec8

File tree

8 files changed

+97
-29
lines changed

8 files changed

+97
-29
lines changed

app/src/main/java/vocabletrainer/heinecke/aron/vocabletrainer/dialog/ImportLogDialog.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import android.support.v7.app.AlertDialog;
99

1010
import vocabletrainer.heinecke.aron.vocabletrainer.R;
11+
import vocabletrainer.heinecke.aron.vocabletrainer.lib.ViewModel.ImportViewModel;
1112

1213
/**
1314
* Dialog showing the log after importing has finished.
@@ -16,13 +17,15 @@
1617
public class ImportLogDialog extends DialogFragment {
1718
public static final String TAG = "LogFragment";
1819
private static final String LOG = "log";
20+
private static final String PREVIEW = "preview";
1921
/**
2022
* Creates a new instance
2123
*/
22-
public static ImportLogDialog newInstance(final String log){
24+
public static ImportLogDialog newInstance(final ImportViewModel.LogData log){
2325
ImportLogDialog dialog = new ImportLogDialog();
2426
Bundle args = new Bundle();
25-
args.putString(LOG, log);
27+
args.putString(LOG, log.log);
28+
args.putBoolean(PREVIEW,log.isPreview);
2629
dialog.setArguments(args);
2730
return dialog;
2831
}
@@ -38,7 +41,8 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
3841
public Dialog onCreateDialog(Bundle savedInstanceState) {
3942

4043
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
41-
alertDialog.setTitle(R.string.Import_Finished_Title);
44+
alertDialog.setTitle(getArguments().getBoolean(PREVIEW) ?
45+
R.string.Import_Preview_Log_Title : R.string.Import_Finished_Title);
4246
alertDialog.setMessage(getArguments().getString(LOG));
4347

4448
alertDialog.setPositiveButton(R.string.GEN_OK, (dialog, whichButton) -> this.dismiss());

app/src/main/java/vocabletrainer/heinecke/aron/vocabletrainer/fragment/ExportFragment.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
109109
}
110110
});
111111

112+
exportViewModel.getExceptionHandle().observe(this, error -> {
113+
if(error != null){
114+
final AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
115+
alert.setCancelable(true);
116+
alert.setTitle(R.string.Export_Error_Info_Title);
117+
alert.setMessage(error);
118+
alert.setPositiveButton(R.string.GEN_OK, (dialogInterface, i) -> {
119+
// do nothing, dismiss dialog
120+
});
121+
alert.show();
122+
exportViewModel.resetException();
123+
}
124+
});
125+
112126
exportViewModel.getCancelExportHandle().observe(this, data -> {
113127
if(data != null && data){
114128
Toast.makeText(getContext(),R.string.Export_Cancel_Toast, Toast.LENGTH_SHORT).show();

app/src/main/java/vocabletrainer/heinecke/aron/vocabletrainer/fragment/ImportFragment.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ public void onCreate(@Nullable Bundle savedInstanceState) {
105105
importViewModel = ViewModelProviders.of(getActivity()).get(ImportViewModel.class);
106106
FormatViewModel formatViewModel = ViewModelProviders.of(getActivity()).get(FormatViewModel.class);
107107

108-
importViewModel.getLogHandle().observe(this, log -> {
109-
if(log != null && log.length() > 1) {
110-
ImportLogDialog logDialog = ImportLogDialog.newInstance(log);
108+
importViewModel.getLogHandle().observe(this, logData -> {
109+
if(logData != null && logData.log.length() > 0) {
110+
ImportLogDialog logDialog = ImportLogDialog.newInstance(logData);
111111
logDialog.show(getACActivity().getSupportFragmentManager(),ImportLogDialog.TAG);
112112
importViewModel.resetLog();
113113
}

app/src/main/java/vocabletrainer/heinecke/aron/vocabletrainer/lib/CSV/Exporter.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,25 @@ public class Exporter extends AsyncTask<Integer, Integer, String> {
2828
private final static String TAG = "ExportTask";
2929
private final ExportFragment.ExportStorage es;
3030
private final Database db;
31-
private MutableLiveData<Integer> progressHandle;
31+
private final MutableLiveData<Integer> progressHandle;
3232
private final Function<Void,String> exportCallback;
3333
private final Function<Void,String> cancelCallback;
34+
private final MutableLiveData<String> exceptionHandle;
3435

3536
/**
3637
* Creates a new ExportOperation
3738
*
3839
* @param es
3940
*/
4041
public Exporter(ExportFragment.ExportStorage es, MutableLiveData<Integer> progressHandle,
41-
Function<Void,String> exportCallback,Function<Void,String> cancelCallback, Context context) {
42+
Function<Void,String> exportCallback,Function<Void,String> cancelCallback, Context context,
43+
MutableLiveData<String> exceptionHandle) {
4244
this.es = es;
4345
this.progressHandle = progressHandle;
4446
this.exportCallback = exportCallback;
4547
this.cancelCallback = cancelCallback;
4648
db = new Database(context);
49+
this.exceptionHandle = exceptionHandle;
4750
}
4851

4952
@Override
@@ -89,7 +92,8 @@ protected String doInBackground(Integer... params) {
8992
publishProgress(i);
9093
}
9194
} catch (Exception e) {
92-
Log.wtf(TAG, e);
95+
exceptionHandle.postValue("Exception: "+e);
96+
Log.e(TAG,"Export exception", e);
9397
}
9498

9599
return null;

app/src/main/java/vocabletrainer/heinecke/aron/vocabletrainer/lib/CSV/Import/ImportFetcher.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class ImportFetcher extends AsyncTask<Integer, Integer, String> {
4444
private final MessageProvider messageProvider;
4545
private final Function<Void,String> importCallback;
4646
private final Function<Void,String> cancelCallback;
47-
private final boolean logErrors;
47+
private final boolean logEverything;
4848
private long lastUpdate = 0;
4949
private StringBuilder log;
5050

@@ -59,21 +59,21 @@ public class ImportFetcher extends AsyncTask<Integer, Integer, String> {
5959
* @param progressHandle Progress handle<br>
6060
* @param messageProvider Message provider for logs
6161
* @param importCallback callback after successful import, given import log as param, return ignored
62-
* @param logErrors disable error logging on false
62+
* @param logEverything whether to log all or exceptions only (preview vs import)
6363
* @param cancelCallback Callback to be executed on cancel action
6464
*/
6565
ImportFetcher(final CSVCustomFormat cformat, final File source, final ImportHandler handler,
6666
final MutableLiveData<Integer> progressHandle,
6767
final MessageProvider messageProvider, final Function<Void,String> importCallback,
68-
final boolean logErrors,@Nullable final Function<Void,String> cancelCallback) {
68+
final boolean logEverything, @Nullable final Function<Void,String> cancelCallback) {
6969
this.source = source;
7070
this.cformat = cformat;
7171
this.handler = handler;
7272
this.progressHandle = progressHandle;
7373
this.log = new StringBuilder();
7474
this.messageProvider = messageProvider;
7575
this.importCallback = importCallback;
76-
this.logErrors = logErrors;
76+
this.logEverything = logEverything;
7777
this.cancelCallback = cancelCallback;
7878
}
7979

@@ -135,14 +135,14 @@ protected String doInBackground(Integer... params) {
135135
}
136136

137137
if (record.size() < MIN_RECORD_SIZE) { // ignore, not enough values
138-
if(logErrors) {
138+
if(logEverything) {
139139
Log.w(TAG, "ignoring entry, missing values: " + record.toString());
140140
log.append(messageProvider.E_NOT_ENOUGH_VALUES);
141141
log.append(recordToString(record));
142142
log.append('\n');
143143
}
144144
continue;
145-
} else if (record.size() > MAX_RECORD_SIZE && logErrors) { // warn, too many values
145+
} else if (record.size() > MAX_RECORD_SIZE && logEverything) { // warn, too many values
146146
Log.w(TAG, "entry longer then necessary: " + record.toString());
147147
log.append(messageProvider.W_TOO_MANY_VALUES);
148148
log.append(recordToString(record));
@@ -155,21 +155,25 @@ protected String doInBackground(Integer... params) {
155155
handler.newTable(v1, v2, v3);
156156
tbl_start = false;
157157
} else //noinspection StatementWithEmptyBody
158+
{
158159
if (tbl_start = (v1.equals(CSV_METADATA_START[0]) && v2.equals(CSV_METADATA_START[1]) && v3.equals(CSV_METADATA_START[2]))) {
159-
//do nothing
160-
} else {
161-
vocableAmount++;
162-
List<String> mA = multiMeaningHandler.parseMultiMeaning(v1);
163-
List<String> mB = multiMeaningHandler.parseMultiMeaning(v2);
164-
String addition = record.size() < ADDITION_RECORD_SIZE ? empty_v : record.get(REC_V4);
165-
handler.newEntry(mA, mB, v3,addition);
160+
//do nothing
161+
} else {
162+
vocableAmount++;
163+
List<String> mA = multiMeaningHandler.parseMultiMeaning(v1);
164+
List<String> mB = multiMeaningHandler.parseMultiMeaning(v2);
165+
String addition = record.size() < ADDITION_RECORD_SIZE ? empty_v : record.get(REC_V4);
166+
handler.newEntry(mA, mB, v3,addition);
167+
}
166168
}
167169
}
168170
//prepend to start
169-
if(!isCancelled())
171+
if(!isCancelled() && logEverything)
170172
log.insert(0,messageProvider.formatIMPORTED_AMOUNT(vocableAmount));
171173
} catch (Exception e) {
172-
Log.e(TAG, "", e);
174+
log.append("Exception: ");
175+
log.append(e.toString());
176+
Log.e(TAG, "Import exception", e);
173177
} finally {
174178
if(this.isCancelled())
175179
handler.cancel();

app/src/main/java/vocabletrainer/heinecke/aron/vocabletrainer/lib/ViewModel/ExportViewModel.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public class ExportViewModel extends ViewModel {
2222
private MutableLiveData<Boolean> exporting;
2323
private MutableLiveData<Boolean> cancelExport;
2424
private MutableLiveData<Boolean> exportFinished;
25+
private MutableLiveData<String> exception;
2526
private Observer<Boolean> observeCancel;
2627
private AsyncTask task;
2728

@@ -31,6 +32,7 @@ public ExportViewModel() {
3132
exporting = new MutableLiveData<>();
3233
cancelExport = new MutableLiveData<>();
3334
exportFinished = new MutableLiveData<>();
35+
exception = new MutableLiveData<>();
3436
cancelExport.setValue(false);
3537
exporting.setValue(false);
3638
progressExport.setValue(0);
@@ -42,6 +44,21 @@ public ExportViewModel() {
4244
cancelExport.observeForever(observeCancel);
4345
}
4446

47+
/**
48+
* Resets exception back to null (none)
49+
*/
50+
public void resetException(){
51+
exception.setValue(null);
52+
}
53+
54+
/**
55+
* Returns exception handle, for error reporting
56+
* @return
57+
*/
58+
public LiveData<String> getExceptionHandle() {
59+
return exception;
60+
}
61+
4562
/**
4663
* Get cancelExport handle
4764
* @return mutable LiveData handle for cancelling export
@@ -113,10 +130,12 @@ public void runExport(Context context, ExportFragment.ExportStorage exportStorag
113130
return null;
114131
};
115132

116-
Exporter exporter = new Exporter(exportStorage,progressExport,callback,callbackCancel,context);
133+
Exporter exporter = new Exporter(exportStorage,progressExport,callback,callbackCancel,context,
134+
exception);
117135
this.exportListAmount = exportStorage.lists.size();
118136
this.progressExport.setValue(0); // don't start on max on redo
119137
this.exporting.setValue(true);
138+
resetException();
120139
task = exporter.execute(0); // 0 is just to pass something
121140
}
122141

app/src/main/java/vocabletrainer/heinecke/aron/vocabletrainer/lib/ViewModel/ImportViewModel.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class ImportViewModel extends ViewModel {
3333
private MutableLiveData<Boolean> reparsing;
3434
private MutableLiveData<Boolean> importing;
3535
private MutableLiveData<Integer> progress;
36-
private MutableLiveData<String> importLog;
36+
private MutableLiveData<LogData> importLog; // also preview parsing, see data container
3737
private MutableLiveData<Boolean> cancelPreview; // cancelPreview parser thread trigger
3838
private MutableLiveData<Boolean> cancelImport;
3939
private boolean isMultiList;
@@ -46,6 +46,24 @@ public class ImportViewModel extends ViewModel {
4646
private Observer<Boolean> observerCancel;
4747
private AsyncTask parserThread;
4848

49+
/**
50+
* Log Data container
51+
*/
52+
public static class LogData{
53+
public final String log;
54+
public final boolean isPreview;
55+
56+
/**
57+
* New Log data container
58+
* @param log Log data
59+
* @param isPreview whether it's preview data or not
60+
*/
61+
public LogData(@NonNull String log, boolean isPreview) {
62+
this.log = log;
63+
this.isPreview = isPreview;
64+
}
65+
}
66+
4967
/**
5068
* Start preview parsing
5169
* @param format
@@ -60,6 +78,7 @@ public void previewParse(@NonNull CSVCustomFormat format, @NonNull File impFile,
6078
setRawData(dataHandler.isRawData());
6179
setPreviewParser(dataHandler);
6280
updateIsReparsing(false);
81+
importLog.setValue(new LogData(param,true)); // show logged exceptions during preview parsing
6382
return null;
6483
};
6584
Function<Void,String> callbackCancel = param -> {
@@ -89,7 +108,7 @@ public void runImport(@NonNull Importer dataHandler, @NonNull CSVCustomFormat fo
89108
return;
90109
Function<Void,String> callback = param -> {
91110
importing.setValue(false);
92-
importLog.setValue(param);
111+
importLog.setValue(new LogData(param,false));
93112
cancelImport.setValue(false);
94113
return null;
95114
};
@@ -137,7 +156,7 @@ protected void onCleared() {
137156
* Returns import log live data
138157
* @return
139158
*/
140-
public LiveData<String> getLogHandle() {
159+
public LiveData<LogData> getLogHandle() {
141160
return importLog;
142161
}
143162

@@ -174,7 +193,7 @@ public void setRawData(boolean rawData) {
174193
}
175194

176195
/**
177-
* Update preview parser & update previewData
196+
* Update preview parser & update preview data
178197
* @param parser
179198
*/
180199
public void setPreviewParser(@NonNull PreviewParser parser){

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@
7070
<string name="Import_File_select_Info">Select import source file</string>
7171
<string name="Import_Preview_Update_Title">Updating..</string>
7272
<string name="Import_Importing_Title">Importing..</string>
73+
<!-- result dialog title -->
7374
<string name="Import_Finished_Title">Importing finished</string>
75+
<!-- exception dialog title for preview parsing -->
76+
<string name="Import_Preview_Log_Title">Preview log</string>
7477
<string name="Import_Preview_Loading">Loading data..</string>
7578
<string name="Import_Preview_No_data">No data to display..</string>
7679
<string name="Import_Cancel_Toast_Preview">Please reparse to continue</string>
@@ -88,6 +91,7 @@
8891
<string name="Export_Exporting_Title">Exporting..</string>
8992
<string name="Export_Error_Format_Multivalue_Title">Invalid CSV Format</string>
9093
<string name="Export_Error_Format_Multivalue_Text">Export requires a CSV Format with multi-value support to avoid data loss.</string>
94+
<string name="Export_Error_Info_Title">Export Error:</string>
9195
<string name="File_btn_Cancel">Cancel</string>
9296
<string name="File_Loading">Loading..</string>
9397
<string name="File_t_hint">File_Name.xyz</string>

0 commit comments

Comments
 (0)