Refactored TrackImporter interface.

This commit is contained in:
Dennis Guse
2021-02-28 18:37:11 +01:00
parent 0f89cd7875
commit 508af45449
6 changed files with 48 additions and 41 deletions
@@ -148,7 +148,7 @@ public class ExportImportTest {
// 2. import // 2. import
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context); AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
// then // then
// 1. track // 1. track
@@ -187,7 +187,7 @@ public class ExportImportTest {
// 2. import // 2. import
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context); AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
// then // then
// 1. track // 1. track
@@ -225,7 +225,7 @@ public class ExportImportTest {
// 2. import // 2. import
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context); AbstractFileTrackImporter trackImporter = new KmlFileTrackImporter(context);
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
// then // then
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
@@ -281,7 +281,7 @@ public class ExportImportTest {
// 2. import // 2. import
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
AbstractFileTrackImporter trackImporter = new GpxFileTrackImporter(context, contentProviderUtils); AbstractFileTrackImporter trackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
// then // then
// 1. track // 1. track
@@ -327,7 +327,7 @@ public class ExportImportTest {
// 2. import // 2. import
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
AbstractFileTrackImporter trackImporter = new GpxFileTrackImporter(context, contentProviderUtils); AbstractFileTrackImporter trackImporter = new GpxFileTrackImporter(context, contentProviderUtils);
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
// then // then
// 1. track // 1. track
@@ -54,7 +54,7 @@ public class LegacyImportTest {
// when // when
// 1. import // 1. import
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
// then // then
// 1. track // 1. track
@@ -95,7 +95,7 @@ public class LegacyImportTest {
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_kml_empty); InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_kml_empty);
// when // when
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
} }
/** /**
@@ -110,7 +110,7 @@ public class LegacyImportTest {
// when // when
// 1. import // 1. import
importTrackId = trackImporter.importFile(inputStream); importTrackId = trackImporter.importFile(inputStream).get(0);
// then // then
// 1. track // 1. track
@@ -120,10 +120,11 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
} }
@Override @Override
public Track.Id importFile(InputStream inputStream) { @NonNull
public List<Track.Id> importFile(InputStream inputStream) {
try { try {
SAXParserFactory.newInstance().newSAXParser().parse(inputStream, this); SAXParserFactory.newInstance().newSAXParser().parse(inputStream, this);
return trackIds.get(0); return trackIds;
} catch (IOException | SAXException | ParserConfigurationException | ParsingException e) { } catch (IOException | SAXException | ParserConfigurationException | ParsingException e) {
Log.e(TAG, "Unable to import file", e); Log.e(TAG, "Unable to import file", e);
if (trackIds.size() > 0) { if (trackIds.size() > 0) {
@@ -14,6 +14,7 @@ import androidx.documentfile.provider.DocumentFile;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Track;
@@ -62,11 +63,12 @@ public class ImportService extends JobIntentService {
} }
try (InputStream inputStream = getContentResolver().openInputStream(file.getUri())) { try (InputStream inputStream = getContentResolver().openInputStream(file.getUri())) {
Track.Id trackId = trackImporter.importFile(inputStream); ArrayList<Track.Id> trackIds = new ArrayList<>(trackImporter.importFile(inputStream));
if (trackId != null) {
sendResult(ImportServiceResultReceiver.RESULT_CODE_IMPORTED, trackId, file, getString(R.string.import_file_imported, file.getName())); if (!trackIds.isEmpty()) {
sendResult(ImportServiceResultReceiver.RESULT_CODE_IMPORTED, trackIds, file, getString(R.string.import_file_imported, file.getName()));
} else { } else {
sendResult(ImportServiceResultReceiver.RESULT_CODE_ERROR, trackId, file, getString(R.string.import_unable_to_import_file, file.getName())); sendResult(ImportServiceResultReceiver.RESULT_CODE_ERROR, trackIds, file, getString(R.string.import_unable_to_import_file, file.getName()));
} }
} catch (IOException e) { } catch (IOException e) {
Log.d(TAG, "Unable to import file", e); Log.d(TAG, "Unable to import file", e);
@@ -80,9 +82,9 @@ public class ImportService extends JobIntentService {
} }
} }
private void sendResult(int resultCode, Track.Id trackId, DocumentFile file, String message) { private void sendResult(int resultCode, ArrayList<Track.Id> trackId, DocumentFile file, String message) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putParcelable(ImportServiceResultReceiver.RESULT_EXTRA_TRACK_ID, trackId); bundle.putParcelableArrayList(ImportServiceResultReceiver.RESULT_EXTRA_TRACK_ID, trackId);
bundle.putString(ImportServiceResultReceiver.RESULT_EXTRA_FILENAME, file.getName()); bundle.putString(ImportServiceResultReceiver.RESULT_EXTRA_FILENAME, file.getName());
bundle.putString(ImportServiceResultReceiver.RESULT_EXTRA_MESSAGE, message); bundle.putString(ImportServiceResultReceiver.RESULT_EXTRA_MESSAGE, message);
resultReceiver.send(resultCode, bundle); resultReceiver.send(resultCode, bundle);
@@ -20,6 +20,8 @@ import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@@ -66,17 +68,23 @@ public class KmzTrackImporter implements TrackImporter {
} }
@Override @Override
public Track.Id importFile(InputStream inputStream) { public @NonNull
Track.Id trackId = findAndParseKmlFile(inputStream); List<Track.Id> importFile(InputStream inputStream) {
List<Track.Id> trackIds = findAndParseKmlFile(inputStream);
if (!copyKmzImages(trackId)) { ArrayList<Track.Id> trackIdsWithImages = new ArrayList<>();
cleanImport(context, trackId);
return null; for (Track.Id trackId : trackIds) {
if (copyKmzImages(trackId)) {
trackIdsWithImages.add(trackId);
deleteOrphanImages(context, trackId);
} else {
cleanImport(context, trackId);
return new ArrayList<>();
}
} }
deleteOrphanImages(context, trackId); return trackIdsWithImages;
return trackId;
} }
/** /**
@@ -150,14 +158,13 @@ public class KmzTrackImporter implements TrackImporter {
/** /**
* Finds KmzTrackExporter.KMZ_KML_FILE file inside kmz file (inputStream) and it parses it. * Finds KmzTrackExporter.KMZ_KML_FILE file inside kmz file (inputStream) and it parses it.
* TODO: May load multiple tracks, but only returns the last Track.Id.
* *
* @param inputStream kmz input stream. * @param inputStream kmz input stream.
*/ */
private Track.Id findAndParseKmlFile(InputStream inputStream) { private List<Track.Id> findAndParseKmlFile(InputStream inputStream) {
try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) { try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
ZipEntry zipEntry; ZipEntry zipEntry;
Track.Id trackId = null; ArrayList<Track.Id> trackIds = new ArrayList<>();
while ((zipEntry = zipInputStream.getNextEntry()) != null) { while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (Thread.interrupted()) { if (Thread.interrupted()) {
@@ -167,20 +174,21 @@ public class KmzTrackImporter implements TrackImporter {
String fileName = zipEntry.getName(); String fileName = zipEntry.getName();
if (KmzTrackExporter.KMZ_KML_FILE.equals(fileName)) { if (KmzTrackExporter.KMZ_KML_FILE.equals(fileName)) {
trackId = parseKml(zipInputStream); List<Track.Id> trackId = parseKml(zipInputStream);
if (trackId == null) { if (trackId.isEmpty()) {
Log.d(TAG, "Unable to parse kml in kmz"); Log.d(TAG, "Unable to parse kml in kmz");
throw new ImportParserException(context.getString(R.string.import_unable_to_import_file, fileName)); throw new ImportParserException(context.getString(R.string.import_unable_to_import_file, fileName));
} }
trackIds.addAll(trackId);
} }
zipInputStream.closeEntry(); zipInputStream.closeEntry();
} }
if (trackId == null) { if (trackIds.isEmpty()) {
Log.d(TAG, "Unable to find doc.kml in kmz"); Log.d(TAG, "Unable to find doc.kml in kmz");
throw new ImportParserException(context.getString(R.string.import_no_kml_file_found)); throw new ImportParserException(context.getString(R.string.import_no_kml_file_found));
} }
return trackId; return trackIds;
} catch (ImportParserException | ImportAlreadyExistsException e) { } catch (ImportParserException | ImportAlreadyExistsException e) {
Log.e(TAG, "Unable to import file", e); Log.e(TAG, "Unable to import file", e);
throw e; throw e;
@@ -234,13 +242,7 @@ public class KmzTrackImporter implements TrackImporter {
} }
} }
/** private List<Track.Id> parseKml(ZipInputStream zipInputStream) {
* Parses kml
*
* @param zipInputStream the zip input stream
* @return the imported track id or -1L
*/
private Track.Id parseKml(ZipInputStream zipInputStream) {
KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context); KmlFileTrackImporter kmlFileTrackImporter = new KmlFileTrackImporter(context);
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getKml(zipInputStream))) { try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getKml(zipInputStream))) {
@@ -15,7 +15,10 @@
*/ */
package de.dennisguse.opentracks.io.file.importer; package de.dennisguse.opentracks.io.file.importer;
import androidx.annotation.NonNull;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.Track;
@@ -30,8 +33,7 @@ public interface TrackImporter {
* Import a file. * Import a file.
* *
* @param inputStream the file's input stream * @param inputStream the file's input stream
* @return the imported track id or null.
*/ */
//TODO Figure out how can make the import an atomic operation (incl. database transaction rollback). @NonNull
Track.Id importFile(InputStream inputStream); List<Track.Id> importFile(InputStream inputStream) throws ImportParserException;
} }