diff options
| -rw-r--r-- | main/src/cgeo/geocaching/cgeogpxes.java | 8 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/files/GPXImporter.java | 71 | ||||
| -rw-r--r-- | tests/res/raw/pq7545915.zip | bin | 0 -> 5086 bytes | |||
| -rw-r--r-- | tests/src/cgeo/geocaching/cgeogpxesTest.java | 5 | ||||
| -rw-r--r-- | tests/src/cgeo/geocaching/files/GPXImporterTest.java | 72 |
5 files changed, 138 insertions, 18 deletions
diff --git a/main/src/cgeo/geocaching/cgeogpxes.java b/main/src/cgeo/geocaching/cgeogpxes.java index 6ac2f0c..ce9b437 100644 --- a/main/src/cgeo/geocaching/cgeogpxes.java +++ b/main/src/cgeo/geocaching/cgeogpxes.java @@ -12,12 +12,15 @@ import android.os.Environment; import java.io.File; import java.util.List; +import java.util.regex.Pattern; public class cgeogpxes extends FileList<cgGPXListAdapter> { private static final String EXTRAS_LIST_ID = "list"; + private static final Pattern gpxZipFilePattern = Pattern.compile("\\d+\\.zip", Pattern.CASE_INSENSITIVE); + public cgeogpxes() { - super(new String[] { "gpx", "loc" }); + super(new String[] { "gpx", "loc", "zip" }); } private int listId = 1; @@ -59,6 +62,9 @@ public class cgeogpxes extends FileList<cgGPXListAdapter> { @Override protected boolean filenameBelongsToList(final String filename) { if (super.filenameBelongsToList(filename)) { + if (StringUtils.endsWithIgnoreCase(filename, GPXImporter.ZIP_FILE_EXTENSION)) { + return gpxZipFilePattern.matcher(filename).matches(); + } // filter out waypoint files return !StringUtils.endsWithIgnoreCase(filename, GPXImporter.WAYPOINTS_FILE_SUFFIX_AND_EXTENSION); } diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index 4ee7e99..65b0189 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -27,6 +27,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.concurrent.CancellationException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; public class GPXImporter { static final int IMPORT_STEP_READ_FILE = 1; @@ -38,6 +40,7 @@ public class GPXImporter { static final int IMPORT_STEP_CANCELED = 7; public static final String GPX_FILE_EXTENSION = ".gpx"; + public static final String ZIP_FILE_EXTENSION = ".zip"; public static final String WAYPOINTS_FILE_SUFFIX_AND_EXTENSION = "-wpts.gpx"; private Progress progress = new Progress(); @@ -57,6 +60,8 @@ public class GPXImporter { public void importGPX(final File file) { if (StringUtils.endsWithIgnoreCase(file.getName(), GPX_FILE_EXTENSION)) { new ImportGpxFileThread(file, listId, importStepHandler, progressHandler).start(); + } else if (StringUtils.endsWithIgnoreCase(file.getName(), ZIP_FILE_EXTENSION)) { + new ImportGpxZipFileThread(file, listId, importStepHandler, progressHandler).start(); } else { new ImportLocFileThread(file, listId, importStepHandler, progressHandler).start(); } @@ -148,7 +153,7 @@ public class GPXImporter { caches = parser.parse(cacheFile, progressHandler); } - final File wptsFile = getWaypointsFileForGpx(cacheFile); + final File wptsFile = new File(cacheFile.getParentFile(), getWaypointsFileNameForGpxFileName(cacheFile.getName())); if (wptsFile != null && wptsFile.canRead()) { Log.i(Settings.tag, "Import GPX waypoint file: " + wptsFile.getAbsolutePath()); importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) wptsFile.length())); @@ -159,6 +164,55 @@ public class GPXImporter { } } + static class ImportGpxZipFileThread extends ImportThread { + private final File cacheFile; + + public ImportGpxZipFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + this.cacheFile = file; + } + + @Override + protected Collection<cgCache> doImport() throws IOException, ParserException { + Log.i(Settings.tag, "Import GPX zip file: " + cacheFile.getAbsolutePath()); + ZipFile zipFile = new ZipFile(cacheFile); + try { + final String gpxName = getGpxFileNameForZipFileName(cacheFile.getName()); + if (gpxName == null) { + throw new ParserException(cacheFile.getName() + " is not a GPX zip file"); + } + final ZipEntry gpxEntry = zipFile.getEntry(gpxName); + if (gpxEntry == null) { + throw new ParserException(cacheFile.getName() + " is not a GPX zip file"); + } + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) gpxEntry.getSize())); + + Collection<cgCache> caches; + GPXParser parser; + try { + // try to parse cache file as GPX 10 + parser = new GPX10Parser(listId); + caches = parser.parse(zipFile.getInputStream(gpxEntry), progressHandler); + } catch (ParserException pe) { + // didn't work -> lets try GPX11 + parser = new GPX11Parser(listId); + caches = parser.parse(zipFile.getInputStream(gpxEntry), progressHandler); + } + + final ZipEntry gpxWptsEntry = zipFile.getEntry(getWaypointsFileNameForGpxFileName(gpxName)); + if (gpxWptsEntry != null) { + Log.i(Settings.tag, "Import GPX waypoint file: " + gpxWptsEntry.getName()); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) gpxWptsEntry.getSize())); + caches = parser.parse(zipFile.getInputStream(gpxWptsEntry), progressHandler); + } + + return caches; + } finally { + zipFile.close(); + } + } + } + static class ImportLocFileThread extends ImportThread { private final File file; @@ -263,12 +317,19 @@ public class GPXImporter { } }; + // 1234567.zip -> 1234567.gpx + static String getGpxFileNameForZipFileName(String name) { + if (StringUtils.endsWithIgnoreCase(name, ZIP_FILE_EXTENSION) && (StringUtils.length(name) > ZIP_FILE_EXTENSION.length())) { + return StringUtils.substringBeforeLast(name, ".") + GPX_FILE_EXTENSION; + } else { + return null; + } + } + // 1234567.gpx -> 1234567-wpts.gpx - static File getWaypointsFileForGpx(File file) { - final String name = file.getName(); + static String getWaypointsFileNameForGpxFileName(String name) { if (StringUtils.endsWithIgnoreCase(name, GPX_FILE_EXTENSION) && (StringUtils.length(name) > GPX_FILE_EXTENSION.length())) { - final String wptsName = StringUtils.substringBeforeLast(name, ".") + WAYPOINTS_FILE_SUFFIX_AND_EXTENSION; - return new File(file.getParentFile(), wptsName); + return StringUtils.substringBeforeLast(name, ".") + WAYPOINTS_FILE_SUFFIX_AND_EXTENSION; } else { return null; } diff --git a/tests/res/raw/pq7545915.zip b/tests/res/raw/pq7545915.zip Binary files differnew file mode 100644 index 0000000..e23751f --- /dev/null +++ b/tests/res/raw/pq7545915.zip diff --git a/tests/src/cgeo/geocaching/cgeogpxesTest.java b/tests/src/cgeo/geocaching/cgeogpxesTest.java index bc0f99e..884bd03 100644 --- a/tests/src/cgeo/geocaching/cgeogpxesTest.java +++ b/tests/src/cgeo/geocaching/cgeogpxesTest.java @@ -15,12 +15,17 @@ public class cgeogpxesTest extends ActivityInstrumentationTestCase2<cgeogpxes> { assertTrue(importGpxActivity.filenameBelongsToList(".gpx")); assertTrue(importGpxActivity.filenameBelongsToList("1234567.loc")); assertTrue(importGpxActivity.filenameBelongsToList("1234567.LOC")); + assertTrue(importGpxActivity.filenameBelongsToList("1234567.zip")); + assertTrue(importGpxActivity.filenameBelongsToList("1234567.ZIP")); assertFalse(importGpxActivity.filenameBelongsToList("1234567.gpy")); assertFalse(importGpxActivity.filenameBelongsToList("1234567.agpx")); assertFalse(importGpxActivity.filenameBelongsToList("1234567")); assertFalse(importGpxActivity.filenameBelongsToList("")); assertFalse(importGpxActivity.filenameBelongsToList("gpx")); + assertFalse(importGpxActivity.filenameBelongsToList("test.zip")); + assertFalse(importGpxActivity.filenameBelongsToList("zip")); + assertFalse(importGpxActivity.filenameBelongsToList(".zip")); assertFalse(importGpxActivity.filenameBelongsToList("1234567-wpts.gpx")); } diff --git a/tests/src/cgeo/geocaching/files/GPXImporterTest.java b/tests/src/cgeo/geocaching/files/GPXImporterTest.java index d23521b..76648e6 100644 --- a/tests/src/cgeo/geocaching/files/GPXImporterTest.java +++ b/tests/src/cgeo/geocaching/files/GPXImporterTest.java @@ -21,18 +21,32 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { private int listId; private File tempDir; - public static void testGetWaypointsFileForGpx() { - assertEquals(new File("1234567-wpts.gpx"), GPXImporter.getWaypointsFileForGpx(new File("1234567.gpx"))); - assertEquals(new File("/mnt/sdcard/1234567-wpts.gpx"), GPXImporter.getWaypointsFileForGpx(new File("/mnt/sdcard/1234567.gpx"))); - assertEquals(new File("/mnt/sdcard/1-wpts.gpx"), GPXImporter.getWaypointsFileForGpx(new File("/mnt/sdcard/1.gpx"))); - assertEquals(new File("/mnt/sd.card/1-wpts.gpx"), GPXImporter.getWaypointsFileForGpx(new File("/mnt/sd.card/1.gpx"))); - assertEquals(new File("1234567.9-wpts.gpx"), GPXImporter.getWaypointsFileForGpx(new File("1234567.9.gpx"))); - assertEquals(new File("1234567-wpts.gpx"), GPXImporter.getWaypointsFileForGpx(new File("1234567.GPX"))); - assertEquals(new File("gpx.gpx-wpts.gpx"), GPXImporter.getWaypointsFileForGpx(new File("gpx.gpx.gpx"))); - assertNull(GPXImporter.getWaypointsFileForGpx(new File("123.gpy"))); - assertNull(GPXImporter.getWaypointsFileForGpx(new File("gpx"))); - assertNull(GPXImporter.getWaypointsFileForGpx(new File(".gpx"))); - assertNull(GPXImporter.getWaypointsFileForGpx(new File("/mnt/sdcard/.gpx"))); + public void testGetWaypointsFileNameForGpxFileName() { + assertEquals("1234567-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("1234567.gpx")); + assertEquals("/mnt/sdcard/1234567-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("/mnt/sdcard/1234567.gpx")); + assertEquals("/mnt/sdcard/1-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("/mnt/sdcard/1.gpx")); + assertEquals("/mnt/sd.card/1-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("/mnt/sd.card/1.gpx")); + assertEquals("1234567.9-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("1234567.9.gpx")); + assertEquals("1234567-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("1234567.GPX")); + assertEquals("gpx.gpx-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("gpx.gpx.gpx")); + assertEquals("/mnt/sdcard/-wpts.gpx", GPXImporter.getWaypointsFileNameForGpxFileName("/mnt/sdcard/.gpx")); + assertNull(GPXImporter.getWaypointsFileNameForGpxFileName("123.gpy")); + assertNull(GPXImporter.getWaypointsFileNameForGpxFileName("gpx")); + assertNull(GPXImporter.getWaypointsFileNameForGpxFileName(".gpx")); + } + + public void testGetGpxFileNameForZipFileName() { + assertEquals("1234567.gpx", GPXImporter.getGpxFileNameForZipFileName("1234567.zip")); + assertEquals("/mnt/sdcard/1234567.gpx", GPXImporter.getGpxFileNameForZipFileName("/mnt/sdcard/1234567.zip")); + assertEquals("1.gpx", GPXImporter.getGpxFileNameForZipFileName("1.zip")); + assertEquals("/mnt/sd.card/1.gpx", GPXImporter.getGpxFileNameForZipFileName("/mnt/sd.card/1.zip")); + assertEquals("1234567.9.gpx", GPXImporter.getGpxFileNameForZipFileName("1234567.9.zip")); + assertEquals("1234567.gpx", GPXImporter.getGpxFileNameForZipFileName("1234567.ZIP")); + assertEquals("zip.zip.gpx", GPXImporter.getGpxFileNameForZipFileName("zip.zip.zip")); + assertEquals("/mnt/sdcard/.gpx", GPXImporter.getGpxFileNameForZipFileName("/mnt/sdcard/.zip")); + assertNull(GPXImporter.getGpxFileNameForZipFileName("123.zap")); + assertNull(GPXImporter.getGpxFileNameForZipFileName("zip")); + assertNull(GPXImporter.getGpxFileNameForZipFileName(".zip")); } public void testImportGpx() throws IOException { @@ -130,6 +144,40 @@ public class GPXImporterTest extends AbstractResourceInstrumentationTestCase { assertEquals(GPXImporter.IMPORT_STEP_CANCELED, importStepHandler.messages.get(1).what); } + public void testImportGpxZip() throws IOException { + File pq7545915 = new File(tempDir, "7545915.zip"); + copyResourceToFile(R.raw.pq7545915, pq7545915); + + GPXImporter.ImportGpxZipFileThread importThread = new GPXImporter.ImportGpxZipFileThread(pq7545915, listId, importStepHandler, progressHandler); + importThread.run(); + importStepHandler.waitForCompletion(); + + assertEquals(4, importStepHandler.messages.size()); + assertEquals(GPXImporter.IMPORT_STEP_READ_FILE, importStepHandler.messages.get(0).what); + assertEquals(GPXImporter.IMPORT_STEP_READ_WPT_FILE, importStepHandler.messages.get(1).what); + assertEquals(GPXImporter.IMPORT_STEP_STORE_CACHES, importStepHandler.messages.get(2).what); + assertEquals(GPXImporter.IMPORT_STEP_FINISHED, importStepHandler.messages.get(3).what); + cgSearch search = (cgSearch) importStepHandler.messages.get(3).obj; + assertEquals(Collections.singletonList("GC31J2H"), search.getGeocodes()); + + cgCache cache = cgeoapplication.getInstance().getCacheByGeocode("GC31J2H"); + assertCacheProperties(cache); + assertEquals(1, cache.getWaypoints().size()); // this is the original pocket query result without test waypoint + } + + public void testImportGpxZipErr() throws IOException { + // zip file name doesn't match name of gpx entry + File pq1 = new File(tempDir, "1.zip"); + copyResourceToFile(R.raw.pq7545915, pq1); + + GPXImporter.ImportGpxZipFileThread importThread = new GPXImporter.ImportGpxZipFileThread(pq1, listId, importStepHandler, progressHandler); + importThread.run(); + importStepHandler.waitForCompletion(); + + assertEquals(1, importStepHandler.messages.size()); + assertEquals(GPXImporter.IMPORT_STEP_FINISHED_WITH_ERROR, importStepHandler.messages.get(0).what); + } + static class TestHandler extends CancellableHandler { private final List<Message> messages = new ArrayList<Message>(); private long lastMessage = System.currentTimeMillis(); |
