Track export name: first UUID, name and extension (<First 32bits UUID>_<track's name>.<extension>). Fixes #512.

This commit is contained in:
Román Martínez
2021-03-13 14:10:22 +01:00
parent 503cba1315
commit bd48944ad5
4 changed files with 114 additions and 37 deletions
@@ -0,0 +1,60 @@
package de.dennisguse.opentracks.util;
import junit.framework.TestCase;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ExportUtilsTest extends TestCase {
@Test
public void testIsExportFileExists_exists() {
// given
UUID uuid = UUID.randomUUID();
String format = "kmz";
List<String> fileNames = new ArrayList<>();
fileNames.add(uuid.toString().substring(0, 8) + "_name.gpx");
fileNames.add(uuid.toString().substring(0, 8) + "_other name name.kmz");
// when
boolean exists = ExportUtils.isExportFileExists(uuid, format, fileNames);
// then
assertTrue(exists);
}
@Test
public void testIsExportFileExists_not_exists1() {
// given
UUID uuid = UUID.randomUUID();
String format = "gpx";
List<String> fileNames = new ArrayList<>();
fileNames.add(UUID.randomUUID().toString().substring(0, 8) + "_name.gpx");
fileNames.add(UUID.randomUUID().toString().substring(0, 8) + "_other name name.gpx");
// when
boolean exists = ExportUtils.isExportFileExists(uuid, format, fileNames);
// then
assertFalse(exists);
}
@Test
public void testIsExportFileExists_not_exists2() {
// given
UUID uuid = UUID.randomUUID();
String format = "kmz";
List<String> fileNames = new ArrayList<>();
fileNames.add(uuid.toString().substring(0, 8) + "_name.gpx");
fileNames.add(UUID.randomUUID().toString().substring(0, 8) + "_other name name.gpx");
// when
boolean exists = ExportUtils.isExportFileExists(uuid, format, fileNames);
// then
assertFalse(exists);
}
}
@@ -109,6 +109,19 @@ public class Track {
this.trackStatistics = trackStatistics;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Track track = (Track) o;
return id.equals(track.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
public static class Id implements Parcelable {
private final long id;
@@ -91,7 +91,7 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
private ContentProviderUtils contentProviderUtils;
// List of tracks to be exported.
private final ArrayList<Track.Id> trackIds = new ArrayList<>();
private final ArrayList<Track> tracks = new ArrayList<>();
private final LinkedBlockingQueue<PendingConflict> conflictsQueue = new LinkedBlockingQueue<>();
private final Handler conflictsHandler = new Handler();
@@ -187,7 +187,7 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
protected void onDestroy() {
super.onDestroy();
conflictsQueue.clear();
trackIds.clear();
tracks.clear();
}
@Override
@@ -215,11 +215,11 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
for (int i = from; i < trackExportTotalCount; i++) {
cursor.moveToPosition(i);
Track track = ContentProviderUtils.createTrack(cursor);
trackIds.add(track.getId());
tracks.add(track);
}
if (!trackIds.isEmpty()) {
export(trackIds.get(0));
if (!tracks.isEmpty()) {
export(tracks.get(0));
} else {
onExportEnded();
}
@@ -227,26 +227,26 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
}
/**
* Enqueue track identified by trackId to be exported if not exported already or there is a conflict resolution.
* Enqueue track identified by UUID to be exported if not exported already or there is a conflict resolution.
*
* @param trackId the track's id.
* @param track Track object.
* @param conflictResolution conflict resolution to be applied if needed.
*/
private void export(Track.Id trackId, int conflictResolution) {
boolean fileExists = ExportUtils.isExportFileExists(trackId, trackFileFormat.getExtension(), directoryFiles);
private void export(Track track, int conflictResolution) {
boolean fileExists = ExportUtils.isExportFileExists(track.getUuid(), trackFileFormat.getExtension(), directoryFiles);
if (fileExists && conflictResolution == CONFLICT_NONE) {
conflict(trackId);
conflict(track);
} else if (fileExists && conflictResolution == CONFLICT_SKIP) {
trackExportSkippedCount++;
onExportCompleted(trackId);
onExportCompleted(track);
} else {
ExportService.enqueue(this, resultReceiver, trackId, trackFileFormat, directoryUri);
ExportService.enqueue(this, resultReceiver, track.getId(), trackFileFormat, directoryUri);
}
}
private void export(Track.Id trackId) {
export(trackId, autoConflict);
private void export(Track track) {
export(track, autoConflict);
}
private void setConflictVisibility(int visibility) {
@@ -278,14 +278,15 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
viewBinding.exportProgressSummaryErrorsGroup.setVisibility(trackExportErrorCount > 0 ? View.VISIBLE : View.GONE);
}
private void onExportCompleted(Track.Id trackId) {
trackIds.remove(trackId);
private void onExportCompleted(Track track) {
tracks.remove(track);
setProgress();
if (trackIds.isEmpty()) {
if (tracks.isEmpty()) {
onExportEnded();
return;
}
export(trackIds.get(0));
export(tracks.get(0));
}
private void onExportEnded() {
@@ -317,15 +318,15 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
}
Track.Id trackId = resultData.getParcelable(ExportServiceResultReceiver.RESULT_EXTRA_TRACK_ID);
Track track = contentProviderUtils.getTrack(trackId);
switch (resultCode) {
case ExportServiceResultReceiver.RESULT_CODE_ERROR:
trackExportErrorCount++;
Track track = contentProviderUtils.getTrack(trackId);
trackErrors.add(track.getName());
break;
case ExportServiceResultReceiver.RESULT_CODE_SUCCESS:
if (ExportUtils.isExportFileExists(trackId, trackFileFormat.getExtension(), directoryFiles)) {
if (ExportUtils.isExportFileExists(track.getUuid(), trackFileFormat.getExtension(), directoryFiles)) {
trackExportOverwrittenCount++;
} else {
trackExportSuccessCount++;
@@ -335,11 +336,11 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
throw new RuntimeException(TAG + ": export service result code invalid: " + resultCode);
}
onExportCompleted(trackId);
onExportCompleted(track);
}
private void conflict(Track.Id trackId) {
PendingConflict newConflict = new PendingConflict(trackId);
private void conflict(Track track) {
PendingConflict newConflict = new PendingConflict(track);
conflictsQueue.add(newConflict);
if (conflictsQueue.size() == 1) {
@@ -351,10 +352,10 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
* Handle conflicts (exporting file already exists).
*/
private class PendingConflict {
private final Track.Id trackId;
private final Track track;
public PendingConflict(Track.Id trackId) {
this.trackId = trackId;
public PendingConflict(Track track) {
this.track = track;
}
/**
@@ -365,14 +366,13 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
*/
public boolean resolve() {
if (autoConflict == CONFLICT_NONE) {
Track track = contentProviderUtils.getTrack(trackId);
viewBinding.exportProgressAlertIcon.setImageDrawable(ContextCompat.getDrawable(ExportActivity.this, R.drawable.ic_report_problem_24));
viewBinding.exportProgressAlertMsg.setText(getString(R.string.export_track_already_exists_msg, track.getName()));
setConflictVisibility(View.VISIBLE);
return false;
}
export(trackId);
export(track);
return true;
}
@@ -380,7 +380,7 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
* Overwrite the export file and set the autoConflict if user set the "do it for all" switch button.
*/
public void overwrite() {
export(trackId, CONFLICT_OVERWRITE);
export(track, CONFLICT_OVERWRITE);
if (viewBinding.exportProgressApplyToAll.isChecked()) {
autoConflict = CONFLICT_OVERWRITE;
@@ -391,7 +391,7 @@ public class ExportActivity extends FragmentActivity implements ExportServiceRes
* Skip the export file and set the autoConflict if user set the "do it for all" switch button.
*/
public void skip() {
export(trackId, CONFLICT_SKIP);
export(track, CONFLICT_SKIP);
if (viewBinding.exportProgressApplyToAll.isChecked()) {
autoConflict = CONFLICT_SKIP;
@@ -14,6 +14,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
@@ -37,7 +39,7 @@ public class ExportUtils {
public static boolean exportTrack(Context context, TrackFileFormat trackFileFormat, DocumentFile directory, Track track) {
TrackExporter trackExporter = trackFileFormat.createTrackExporter(context);
Uri exportDocumentFileUri = getExportDocumentFileUri(context, track.getId(), trackFileFormat, directory);
Uri exportDocumentFileUri = getExportDocumentFileUri(context, track, trackFileFormat, directory);
if (exportDocumentFileUri == null) {
Log.e(TAG, "Couldn't create document file for export");
return false;
@@ -62,8 +64,10 @@ public class ExportUtils {
}
}
public static boolean isExportFileExists(Track.Id trackId, String trackFileFormatExtension, List<String> filesName) {
return filesName.contains(getExportFileNameByTrackId(trackId, trackFileFormatExtension));
public static boolean isExportFileExists(UUID uuuid, String trackFileFormatExtension, List<String> filesName) {
String word = uuuid.toString().substring(0, 8) + ".*\\." + trackFileFormatExtension;
Pattern pattern = Pattern.compile(word);
return filesName.stream().anyMatch(w -> pattern.matcher(w).matches());
}
public static List<String> getAllFiles(Context context, Uri directoryUri) {
@@ -82,8 +86,8 @@ public class ExportUtils {
return fileNames;
}
private static Uri getExportDocumentFileUri(Context context, Track.Id trackId, TrackFileFormat trackFileFormat, DocumentFile directory) {
String exportFileName = getExportFileNameByTrackId(trackId, trackFileFormat.getExtension());
private static Uri getExportDocumentFileUri(Context context, Track track, TrackFileFormat trackFileFormat, DocumentFile directory) {
String exportFileName = getExportFileNameForTrack(track, trackFileFormat.getExtension());
Uri exportDocumentFileUri = findFile(context, directory.getUri(), exportFileName);
if (exportDocumentFileUri == null) {
final DocumentFile file = directory.createFile(trackFileFormat.getMimeType(), exportFileName);
@@ -94,8 +98,8 @@ public class ExportUtils {
return exportDocumentFileUri;
}
private static String getExportFileNameByTrackId(Track.Id trackId, String trackFileFormatExtension) {
return trackId.getId() + "." + trackFileFormatExtension;
private static String getExportFileNameForTrack(Track track, String trackFileFormatExtension) {
return track.getUuid().toString().substring(0, 8) + "_" + track.getName() + "." + trackFileFormatExtension;
}
private static Uri findFile(Context context, Uri directoryUri, String exportFileName) {