diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java index 1f4149c7e..97545eb53 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/data/TestDataUtil.java @@ -21,7 +21,6 @@ import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Statistics; import de.dennisguse.opentracks.data.models.Track; -import de.dennisguse.opentracks.data.models.TrackBuilder; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.util.AutoCloseableIterator; @@ -92,9 +91,9 @@ public class TestDataUtil { ); List markers = List.of( - new Marker(trackId, trackPoints.get(1), "Marker 1", "Marker description 1", "Marker category 3", "", null), - new Marker(trackId, trackPoints.get(4), "Marker 2", "Marker description 2", "Marker category 3", "", null), - new Marker(trackId, trackPoints.get(5), "Marker 3", "Marker description 3", "Marker category 3", "", null) + new Marker(null, trackId, "Marker 1", "Marker description 1", "Marker category 3", "", trackPoints.get(1).getPosition(),null), + new Marker(null, trackId, "Marker 2", "Marker description 2", "Marker category 3", "", trackPoints.get(4).getPosition(), null), + new Marker(null, trackId, "Marker 3", "Marker description 3", "Marker category 3", "", trackPoints.get(5).getPosition(), null) ); return new TrackData(track, trackPoints, markers); @@ -150,11 +149,23 @@ public class TestDataUtil { } public static Marker createMarkerWithPhoto(Context context, Track.Id trackId, TrackPoint trackPoint) throws IOException { + return createMarkerWithPhoto(context, trackId, trackPoint, "Marker description"); + } + + public static Marker createMarkerWithPhoto(Context context, Track.Id trackId, TrackPoint trackPoint, String description) throws IOException { File dstFile = new File(MarkerUtils.getImageUrl(context, trackId)); dstFile.createNewFile(); Uri photoUri = FileUtils.getUriForFile(context, dstFile); - return new Marker(trackId, trackPoint, "Marker name", "Marker description", "Marker category", "", photoUri); + return new Marker( + null, + trackId, + "Marker name", + description, + "Marker category", + "", + trackPoint.getPosition(), + photoUri); } public static List getTrackPoints(ContentProviderUtils contentProviderUtils, Track.Id trackId) { diff --git a/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java index 1b888c18f..1c72de4b1 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/data/CustomContentProviderUtilsTest.java @@ -57,6 +57,7 @@ import de.dennisguse.opentracks.data.models.AltitudeExtremities; import de.dennisguse.opentracks.data.models.AltitudeGainLoss; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Statistics; @@ -232,8 +233,16 @@ public class CustomContentProviderUtilsTest { Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); - Marker marker = new Marker(trackId, getLastValidTrackPoint(trackId)); - contentProviderUtils.insertMarker(marker); + contentProviderUtils.insertMarker(new Marker( + null, + trackId, + "", + "", + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); assertCount(1, 10, 1); @@ -258,7 +267,7 @@ public class CustomContentProviderUtilsTest { contentProviderUtils.insertMarker(marker); assertCount(1, 10, 1); - assertTrue(marker.hasPhoto()); + assertNotNull(marker.photoUrl()); File dir = FileUtils.getPhotoDir(context, trackId); assertTrue(dir.isDirectory()); assertEquals(1, dir.list().length); @@ -288,8 +297,16 @@ public class CustomContentProviderUtilsTest { TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId2, 10); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId3, 10); - Marker marker = new Marker(trackId1, getLastValidTrackPoint(trackId2)); - contentProviderUtils.insertMarker(marker); + contentProviderUtils.insertMarker(new Marker( + null, + trackId1, + "", + "", + "", + "", + getLastValidTrackPoint(trackId1).getPosition(), + null + )); assertCount(3, 30, 1); @@ -328,7 +345,7 @@ public class CustomContentProviderUtilsTest { // Check. assertCount(3, 30, 2); - assertTrue(marker1.hasPhoto()); + assertNotNull(marker1.photoUrl()); assertTrue(dir1.isDirectory()); assertEquals(1, dir1.list().length); assertTrue(dir1.exists()); @@ -407,9 +424,6 @@ public class CustomContentProviderUtilsTest { assertEquals(nameNew, contentProviderUtils.getTrack(trackId).name()); } - /** - * Tests the method {@link ContentProviderUtils#createContentValues(Marker)}. - */ @Test public void testCreateContentValues_marker() { Track.Id trackId = new Track.Id(System.currentTimeMillis()); @@ -432,15 +446,15 @@ public class CustomContentProviderUtilsTest { )); contentProviderUtils.insertTrack(trackBuilder.getTrack()); - Marker marker = new Marker(trackId, track.second.get(0)); + MarkerBuilder marker = new MarkerBuilder(trackId, track.second.get(0)); marker.setDescription(TEST_DESC); - contentProviderUtils.insertMarker(marker); + contentProviderUtils.insertMarker(marker.getMarker()); ContentProviderUtils contentProviderUtils = new ContentProviderUtils(contentResolverMock); Marker.Id markerId = new Marker.Id(System.currentTimeMillis()); marker.setId(markerId); - ContentValues contentValues = contentProviderUtils.createContentValues(marker); + ContentValues contentValues = contentProviderUtils.createContentValues(marker.getMarker(), trackId); assertEquals(markerId.id(), contentValues.get(MarkerColumns._ID)); assertEquals((int) (TestDataUtil.INITIAL_LONGITUDE * 1000000), contentValues.get(MarkerColumns.LONGITUDE)); assertEquals(TEST_DESC, contentValues.get(MarkerColumns.DESCRIPTION)); @@ -457,15 +471,19 @@ public class CustomContentProviderUtilsTest { TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert at first. - Marker marker1 = new Marker(trackId, getLastValidTrackPoint(trackId)); - marker1.setDescription(TEST_DESC); - contentProviderUtils.insertMarker(marker1); + Marker.Id marker1Id = contentProviderUtils.insertMarker(new Marker( + null, + trackId, + "", + TEST_DESC, + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); // Check insert was done. - assertEquals(1, TestDataUtil.getMarkers(contentProviderUtils, trackId).size()); - - // Get marker id that needs to delete. - Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1); + assertEquals(1, TestDataUtil.getMarkers(contentProviderUtils, trackId).size()); // Delete contentProviderUtils.deleteMarker(context, marker1Id); @@ -495,7 +513,7 @@ public class CustomContentProviderUtilsTest { Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1); // Check marker has photo and it's in the external storage. - assertTrue(marker1.hasPhoto()); + assertNotNull(marker1.photoUrl()); File dir = FileUtils.getPhotoDir(context, trackId); assertTrue(dir.isDirectory()); assertEquals(1, dir.list().length); @@ -534,20 +552,33 @@ public class CustomContentProviderUtilsTest { // TestDataUtil.insertTrackWithLocations(contentProviderUtils, track); // Insert at first. - Marker marker1 = new Marker(trackId, getLastValidTrackPoint(trackId)); - marker1.setDescription(MOCK_DESC); - Marker.Id marker1Id = contentProviderUtils.insertMarker(marker1); - - Marker marker2 = new Marker(trackId, getLastValidTrackPoint(trackId)); - marker2.setDescription(MOCK_DESC); - Marker.Id marker2Id = contentProviderUtils.insertMarker(marker2); + Marker.Id marker1Id = contentProviderUtils.insertMarker(new Marker( + null, + trackId, + "", + MOCK_DESC, + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); + Marker.Id marker2Id = contentProviderUtils.insertMarker(new Marker( + null, + trackId, + "", + MOCK_DESC, + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); // Delete assertNotNull(contentProviderUtils.getMarker(marker1Id)); contentProviderUtils.deleteMarker(context, marker1Id); assertNull(contentProviderUtils.getMarker(marker1Id)); - assertEquals(MOCK_DESC, contentProviderUtils.getMarker(marker2Id).getDescription()); + assertEquals(MOCK_DESC, contentProviderUtils.getMarker(marker2Id).description()); } /** @@ -558,14 +589,18 @@ public class CustomContentProviderUtilsTest { Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); - Marker marker1 = new Marker(trackId, getLastValidTrackPoint(trackId)); - Marker marker2 = new Marker(trackId, getLastValidTrackPoint(trackId)); - Marker marker3 = new Marker(trackId, getLastValidTrackPoint(trackId)); - Marker marker4 = new Marker(trackId, getLastValidTrackPoint(trackId)); - contentProviderUtils.insertMarker(marker1); - contentProviderUtils.insertMarker(marker2); - contentProviderUtils.insertMarker(marker3); - contentProviderUtils.insertMarker(marker4); + for (int i = 0; i < 4; i++) { + contentProviderUtils.insertMarker(new Marker( + null, + trackId, + "", + MOCK_DESC, + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); + } assertEquals(Integer.valueOf(4), contentProviderUtils.getNextMarkerNumber(trackId)); } @@ -579,11 +614,19 @@ public class CustomContentProviderUtilsTest { Track.Id trackId = new Track.Id(System.currentTimeMillis()); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); - Marker marker = new Marker(trackId, getLastValidTrackPoint(trackId)); - marker.setDescription(TEST_DESC); - Marker.Id markerId = contentProviderUtils.insertMarker(marker); + Marker.Id markerId = contentProviderUtils.insertMarker( + new Marker( + null, + trackId, + "", + TEST_DESC, + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); - assertEquals(TEST_DESC, contentProviderUtils.getMarker(markerId).getDescription()); + assertEquals(TEST_DESC, contentProviderUtils.getMarker(markerId).description()); } /** @@ -595,16 +638,31 @@ public class CustomContentProviderUtilsTest { TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); // Insert at first. - Marker marker = new Marker(trackId, getLastValidTrackPoint(trackId)); - marker.setDescription(TEST_DESC); - Marker.Id markerId = contentProviderUtils.insertMarker(marker); + Marker.Id markerId = contentProviderUtils.insertMarker( + new Marker( + null, + trackId, + "", + TEST_DESC, + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); // Update - marker = contentProviderUtils.getMarker(markerId); - marker.setDescription(TEST_DESC_NEW); - contentProviderUtils.updateMarker(context, marker); + contentProviderUtils.updateMarker(context, new Marker( + markerId, + trackId, + "", + TEST_DESC_NEW, + "", + "", + getLastValidTrackPoint(trackId).getPosition(), + null + )); - assertEquals(TEST_DESC_NEW, contentProviderUtils.getMarker(markerId).getDescription()); + assertEquals(TEST_DESC_NEW, contentProviderUtils.getMarker(markerId).description()); } /** @@ -619,9 +677,7 @@ public class CustomContentProviderUtilsTest { // Insert at first. TrackPoint trackPoint = getLastValidTrackPoint(trackId); - Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint); - marker.setDescription(TEST_DESC); - Marker.Id markerId = contentProviderUtils.insertMarker(marker); + Marker.Id markerId = contentProviderUtils.insertMarker(TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint, TEST_DESC)); File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.id()); assertTrue(dir.exists()); @@ -629,14 +685,13 @@ public class CustomContentProviderUtilsTest { assertEquals(1, dir.list().length); // Update - marker = contentProviderUtils.getMarker(markerId); + MarkerBuilder marker = new MarkerBuilder(contentProviderUtils.getMarker(markerId)); marker.setName(TEST_NAME_NEW); marker.setDescription(TEST_DESC_NEW); - contentProviderUtils.updateMarker(context, marker); + contentProviderUtils.updateMarker(context, marker.getMarker()); - assertEquals(TEST_NAME_NEW, contentProviderUtils.getMarker(markerId).getName()); - assertEquals(TEST_DESC_NEW, contentProviderUtils.getMarker(markerId).getDescription()); - assertTrue(marker.hasPhoto()); + assertEquals(TEST_NAME_NEW, contentProviderUtils.getMarker(markerId).name()); + assertEquals(TEST_DESC_NEW, contentProviderUtils.getMarker(markerId).description()); assertTrue(dir.exists()); assertTrue(dir.isDirectory()); assertEquals(1, dir.list().length); @@ -654,8 +709,7 @@ public class CustomContentProviderUtilsTest { // Insert at first. TrackPoint trackPoint = getLastValidTrackPoint(trackId); - Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint); - marker.setDescription(TEST_DESC); + Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint, TEST_DESC); Marker.Id markerId = contentProviderUtils.insertMarker(marker); File dir = new File(FileUtils.getPhotoDir(context), "" + trackId.id()); @@ -664,15 +718,14 @@ public class CustomContentProviderUtilsTest { assertEquals(1, dir.list().length); // Update - marker = contentProviderUtils.getMarker(markerId); - marker.setName(TEST_NAME_NEW); - marker.setDescription(TEST_DESC_NEW); - marker.setPhotoUrl(null); - contentProviderUtils.updateMarker(context, marker); + MarkerBuilder markerBuilder = new MarkerBuilder(contentProviderUtils.getMarker(markerId)); + markerBuilder.setName(TEST_NAME_NEW); + markerBuilder.setDescription(TEST_DESC_NEW); + markerBuilder.setPhotoUrl(null); + contentProviderUtils.updateMarker(context, markerBuilder.getMarker()); - assertEquals(TEST_NAME_NEW, contentProviderUtils.getMarker(markerId).getName()); - assertEquals(TEST_DESC_NEW, contentProviderUtils.getMarker(markerId).getDescription()); - assertFalse(marker.hasPhoto()); + assertEquals(TEST_NAME_NEW, contentProviderUtils.getMarker(markerId).name()); + assertEquals(TEST_DESC_NEW, contentProviderUtils.getMarker(markerId).description()); assertFalse(dir.exists()); } @@ -688,10 +741,8 @@ public class CustomContentProviderUtilsTest { // Insert two markers with photos. TrackPoint trackPoint = getLastValidTrackPoint(trackId); - Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint); - marker.setDescription(TEST_DESC); - Marker otherMarker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint); - otherMarker.setDescription(TEST_DESC); + Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint, TEST_DESC); + Marker otherMarker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint, TEST_DESC); Marker.Id markerId = contentProviderUtils.insertMarker(marker); contentProviderUtils.insertMarker(otherMarker); @@ -701,12 +752,14 @@ public class CustomContentProviderUtilsTest { assertEquals(2, dir.list().length); // Update one marker deleting photo. - marker = contentProviderUtils.getMarker(markerId); - marker.setPhotoUrl(null); - contentProviderUtils.updateMarker(context, marker); + MarkerBuilder markerBuilder = new MarkerBuilder(contentProviderUtils.getMarker(markerId)); + markerBuilder.setPhotoUrl(null); + contentProviderUtils.updateMarker(context, markerBuilder.getMarker()); - assertEquals(TEST_DESC, contentProviderUtils.getMarker(markerId).getDescription()); - assertFalse(marker.hasPhoto()); + // then + marker = contentProviderUtils.getMarker(markerId); + assertEquals(TEST_DESC, contentProviderUtils.getMarker(markerId).description()); + assertNull(marker.photoUrl()); assertTrue(dir.exists()); assertTrue(dir.isDirectory()); assertEquals(1, dir.list().length); diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java index 2bcacac34..d1f343cd2 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java @@ -58,6 +58,7 @@ import de.dennisguse.opentracks.data.models.Cadence; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.HeartRate; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Power; import de.dennisguse.opentracks.data.models.Speed; @@ -152,7 +153,17 @@ public class ExportImportTest { Distance sensorDistance = Distance.of(10); // recording distance interval sendLocation(trackPointCreator, "2020-02-02T02:02:03Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 1f); - contentProviderUtils.insertMarker(new Marker(trackId, service.getLastStoredTrackPointWithLocation(), "Marker 1", "Marker 1 desc", "Marker 1 category", null, null)); + contentProviderUtils.insertMarker( + new Marker( + null, + trackId, + "Marker 1", + "Marker 1 desc", + "Marker 1 category", + null, + service.getLastStoredTrackPointWithLocation().getPosition(), + null + )); // A sensor-only TrackPoint trackPointCreator.setClock("2020-02-02T02:02:04Z"); @@ -166,7 +177,17 @@ public class ExportImportTest { mockSensorData(trackPointCreator, 5f, Distance.of(2), 69f, 3f, 50f, null); // Distance will be added to next TrackPoint sendLocation(trackPointCreator, "2020-02-02T02:02:17Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 0f); - contentProviderUtils.insertMarker(new Marker(trackId, service.getLastStoredTrackPointWithLocation(), "Marker 2", "Marker 2 desc", "Marker 2 category", null, null)); + contentProviderUtils.insertMarker( + new Marker( + null, + trackId, + "Marker 2", + "Marker 2 desc", + "Marker 2 category", + null, + service.getLastStoredTrackPointWithLocation().getPosition(), + null + )); trackPointCreator.setClock("2020-02-02T02:02:18Z"); trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet(trackPointCreator); @@ -195,7 +216,7 @@ public class ExportImportTest { contentProviderUtils.updateTrack(trackBuilder.getTrack()); trackPoints = TestDataUtil.getTrackPoints(contentProviderUtils, trackId); - markers = TestDataUtil.getMarkers(contentProviderUtils, trackId); + markers = TestDataUtil.getMarkers(contentProviderUtils, trackId); } @LargeTest @@ -533,20 +554,20 @@ public class ExportImportTest { private void assertMarkers() { List importedMarkers = TestDataUtil.getMarkers(contentProviderUtils, importTrackId); - assertEquals(markers.size(), importedMarkers.size()); + assertEquals(markers.size(), importedMarkers.size()); for (int i = 0; i < markers.size(); i++) { Marker marker = markers.get(i); Marker importMarker = importedMarkers.get(i); - assertEquals(marker.getCategory(), importMarker.getCategory()); - assertEquals(marker.getDescription(), importMarker.getDescription()); + assertEquals(marker.category(), importMarker.category()); + assertEquals(marker.description(), importMarker.description()); // assertEquals(marker.getIcon(), importMarker.getIcon()); // TODO for KML - assertEquals(marker.getName(), importMarker.getName()); - assertFalse(importMarker.hasPhoto()); + assertEquals(marker.name(), importMarker.name()); + assertNull(importMarker.photoUrl()); - assertEquals(marker.getPosition().latitude(), importMarker.getPosition().latitude(), 0.001); - assertEquals(marker.getPosition().longitude(), importMarker.getPosition().longitude(), 0.001); - assertEquals(marker.getPosition().altitude().toM(), importMarker.getPosition().altitude().toM(), 0.1); + assertEquals(marker.position().latitude(), importMarker.position().latitude(), 0.001); + assertEquals(marker.position().longitude(), importMarker.position().longitude(), 0.001); + assertEquals(marker.position().altitude().toM(), importMarker.position().altitude().toM(), 0.1); } } diff --git a/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java b/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java index fef498ad9..55db65e13 100644 --- a/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java +++ b/src/main/java/de/dennisguse/opentracks/data/ContentProviderUtils.java @@ -50,7 +50,6 @@ import de.dennisguse.opentracks.data.models.Power; import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Statistics; import de.dennisguse.opentracks.data.models.Track; -import de.dennisguse.opentracks.data.models.TrackBuilder; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.tables.MarkerColumns; import de.dennisguse.opentracks.data.tables.TrackPointsColumns; @@ -319,7 +318,7 @@ public class ContentProviderUtils { int latitudeIndex = cursor.getColumnIndexOrThrow(MarkerColumns.LATITUDE); int timeIndex = cursor.getColumnIndexOrThrow(MarkerColumns.TIME); int altitudeIndex = cursor.getColumnIndexOrThrow(MarkerColumns.ALTITUDE); - int accuracyIndex = cursor.getColumnIndexOrThrow(MarkerColumns.ACCURACY); + int accuracyIndex = cursor.getColumnIndexOrThrow(MarkerColumns.HORIZONTAL_ACCURACY); int bearingIndex = cursor.getColumnIndexOrThrow(MarkerColumns.BEARING); int photoUrlIndex = cursor.getColumnIndexOrThrow(MarkerColumns.PHOTOURL); @@ -353,37 +352,27 @@ public class ContentProviderUtils { bearing, null); - Track.Id trackId = new Track.Id(cursor.getLong(trackIdIndex)); - Marker marker = new Marker(trackId, position); - - if (!cursor.isNull(idIndex)) { - marker.setId(new Marker.Id(cursor.getLong(idIndex))); - } - if (!cursor.isNull(nameIndex)) { - marker.setName(cursor.getString(nameIndex)); - } - if (!cursor.isNull(descriptionIndex)) { - marker.setDescription(cursor.getString(descriptionIndex)); - } - if (!cursor.isNull(categoryIndex)) { - marker.setCategory(cursor.getString(categoryIndex)); - } - if (!cursor.isNull(iconIndex)) { - marker.setIcon(cursor.getString(iconIndex)); - } + Uri photoUrl = null; if (!cursor.isNull(photoUrlIndex)) { - String photoUrl = cursor.getString(photoUrlIndex); - if (photoUrl.isEmpty()) { + if (cursor.getString(photoUrlIndex).isEmpty()) { // Before v4.18.0: a marker without a picture as URL "" // TODO Data should be migrated. - marker.setPhotoUrl(null); + photoUrl = null; } else { - marker.setPhotoUrl(Uri.parse(cursor.getString(photoUrlIndex))); + photoUrl = Uri.parse(cursor.getString(photoUrlIndex)); } } - - return marker; + return new Marker( + new Marker.Id(cursor.getLong(idIndex)), + new Track.Id(cursor.getLong(trackIdIndex)), + !cursor.isNull(nameIndex) ? cursor.getString(nameIndex) : "", + !cursor.isNull(descriptionIndex) ? cursor.getString(descriptionIndex) : "", + !cursor.isNull(categoryIndex) ? cursor.getString(categoryIndex) : "", + !cursor.isNull(iconIndex) ? cursor.getString(iconIndex) : "", + position, + photoUrl + ); } public void deleteMarker(Context context, Marker.Id markerId) { @@ -445,24 +434,26 @@ public class ContentProviderUtils { * @return true if successful. */ public boolean updateMarker(Context context, Marker updateMarker) { - Marker savedMarker = getMarker(updateMarker.getId()); - if (!updateMarker.hasPhoto()) { + Marker savedMarker = getMarker(updateMarker.id()); + if (updateMarker.photoUrl() == null) { deleteMarkerPhoto(context, savedMarker); } - int rows = contentResolver.update(MarkerColumns.CONTENT_URI, createContentValues(updateMarker), MarkerColumns._ID + "=?", new String[]{Long.toString(updateMarker.getId().id())}); + int rows = contentResolver.update(MarkerColumns.CONTENT_URI, createContentValues(updateMarker, updateMarker.trackId()), MarkerColumns._ID + "=?", new String[]{Long.toString(updateMarker.id().id())}); return rows == 1; } public Marker.Id insertMarker(@NonNull Marker marker) { - marker.setId(null); - Uri uri = contentResolver.insert(MarkerColumns.CONTENT_URI, createContentValues(marker)); + assert marker.id() == null; + assert marker.trackId() != null; + + Uri uri = contentResolver.insert(MarkerColumns.CONTENT_URI, createContentValues(marker, marker.trackId())); return new Marker.Id(ContentUris.parseId(uri)); } private void deleteMarkerPhoto(Context context, Marker marker) { - if (marker != null && marker.hasPhoto()) { - Uri uri = marker.getPhotoUrl(); - File file = MarkerUtils.buildInternalPhotoFile(context, marker.getTrackId(), uri); + if (marker != null && marker.photoUrl() != null) { + Uri uri = marker.photoUrl(); + File file = MarkerUtils.buildInternalPhotoFile(context, marker.trackId(), uri); if (file.exists()) { File parent = file.getParentFile(); file.delete(); @@ -473,33 +464,33 @@ public class ContentProviderUtils { } } - ContentValues createContentValues(@NonNull Marker marker) { + ContentValues createContentValues(@NonNull Marker marker, @NonNull Track.Id trackId) { ContentValues values = new ContentValues(); - if (marker.getId() != null) { - values.put(MarkerColumns._ID, marker.getId().id()); + if (marker.id() != null) { + values.put(MarkerColumns._ID, marker.id().id()); } - values.put(MarkerColumns.NAME, marker.getName()); - values.put(MarkerColumns.DESCRIPTION, marker.getDescription()); - values.put(MarkerColumns.CATEGORY, marker.getCategory()); - values.put(MarkerColumns.ICON, marker.getIcon()); - values.put(MarkerColumns.TRACKID, marker.getTrackId().id()); - values.put(MarkerColumns.LONGITUDE, (int) (marker.getPosition().longitude() * 1E6)); - values.put(MarkerColumns.LATITUDE, (int) (marker.getPosition().latitude() * 1E6)); - values.put(MarkerColumns.TIME, marker.getTime().toEpochMilli()); - if (marker.hasAltitude()) { - values.put(MarkerColumns.ALTITUDE, marker.getAltitude().toM()); + values.put(MarkerColumns.TRACKID, trackId.id()); + + values.put(MarkerColumns.NAME, marker.name()); + values.put(MarkerColumns.DESCRIPTION, marker.description()); + values.put(MarkerColumns.CATEGORY, marker.category()); + values.put(MarkerColumns.ICON, marker.icon()); + + values.put(MarkerColumns.LONGITUDE, (int) (marker.position().longitude() * 1E6)); + values.put(MarkerColumns.LATITUDE, (int) (marker.position().latitude() * 1E6)); + values.put(MarkerColumns.TIME, marker.position().time().toEpochMilli()); + if (marker.position().hasAltitude()) { + values.put(MarkerColumns.ALTITUDE, marker.position().altitude().toM()); } - if (marker.hasAccuracy()) { - values.put(MarkerColumns.ACCURACY, marker.getAccuracy().toM()); + if (marker.position().hasHorizontalAccuracy()) { + values.put(MarkerColumns.HORIZONTAL_ACCURACY, marker.position().horizontalAccuracy().toM()); } - if (marker.hasBearing()) { - values.put(MarkerColumns.BEARING, marker.getBearing()); + if (marker.position().hasBearing()) { + values.put(MarkerColumns.BEARING, marker.position().bearing()); } - if (marker.hasPhoto()) { - values.put(MarkerColumns.PHOTOURL, marker.getPhotoUrl().toString()); - } + values.put(MarkerColumns.PHOTOURL, marker.photoUrl() != null ? marker.photoUrl().toString() : null); return values; } @@ -603,7 +594,7 @@ public class ContentProviderUtils { public int bulkInsertMarkers(List markers, Track.Id trackId) { ContentValues[] values = new ContentValues[markers.size()]; for (int i = 0; i < markers.size(); i++) { - values[i] = createContentValues(markers.get(i)); + values[i] = createContentValues(markers.get(i), trackId); } return contentResolver.bulkInsert(MarkerColumns.CONTENT_URI, values); } diff --git a/src/main/java/de/dennisguse/opentracks/data/models/Marker.java b/src/main/java/de/dennisguse/opentracks/data/models/Marker.java index f77e05401..5a48adec5 100644 --- a/src/main/java/de/dennisguse/opentracks/data/models/Marker.java +++ b/src/main/java/de/dennisguse/opentracks/data/models/Marker.java @@ -1,19 +1,3 @@ -/* - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - package de.dennisguse.opentracks.data.models; import android.net.Uri; @@ -23,151 +7,32 @@ import android.os.Parcelable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import java.time.Instant; -import java.util.Objects; - /** - * NOTE: A marker is indirectly (via it's {@link Position}) assigned to one {@link TrackPoint} via position.time. - * - * @author Leif Hendrik Wilden - * @author Rodrigo Damazio + * * NOTE: A marker is indirectly (via it's {@link Position}) assigned to one {@link TrackPoint} via position.time. */ -//TODO All data should be final; no default values. -public final class Marker { +public record Marker( - private Id id; - private String name = ""; - private String description = ""; - private String category = ""; - private String icon = ""; - private Track.Id trackId; + @NonNull + Id id, - //Some data might not be used. - private final Position position; + @NonNull + Track.Id trackId, - private Uri photoUrl = null; + @NonNull + String name, + @NonNull + String description, + @NonNull + String category, + @NonNull + String icon, - public Marker(@Nullable Track.Id trackId, @NonNull TrackPoint trackPoint) { - this.trackId = trackId; - - if (!trackPoint.hasLocation()) - throw new RuntimeException("Marker requires a trackpoint with a location."); - - this.position = trackPoint.getPosition(); - } - - public Marker(@Nullable Track.Id trackId, @NonNull Position position) { - this.trackId = trackId; - Objects.requireNonNull(position); - this.position = position; - } - - public Marker(@Nullable Track.Id trackId, @NonNull TrackPoint trackPoint, String name, String description, String category, String icon, Uri photoUrl) { - this(trackId, trackPoint); - this.name = name; - this.description = description; - this.category = category; - this.icon = icon; - this.photoUrl = photoUrl; - } - - /** - * May be null if the Marker was not loaded from the database. - */ - @Nullable - public Id getId() { - return id; - } - - public void setId(Id id) { - this.id = id; - } - - public Instant getTime() { - return position.time(); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getCategory() { - return category; - } - - public void setCategory(String category) { - this.category = category; - } - - public String getIcon() { - return icon; - } - - public void setIcon(String icon) { - this.icon = icon; - } - - public Track.Id getTrackId() { - return trackId; - } - - @Deprecated - public void setTrackId(@NonNull Track.Id trackId) { - this.trackId = trackId; - } - - public Position getPosition() { - return position; - } - - public boolean hasAccuracy() { - return position.hasHorizontalAccuracy(); - } - - public Distance getAccuracy() { - return position.horizontalAccuracy(); - } - - public boolean hasAltitude() { - return position.hasAltitude(); - } - - public Altitude getAltitude() { - return position.altitude(); - } - - public boolean hasBearing() { - return position.hasBearing(); - } - - public Float getBearing() { - return position.bearing(); - } - - public Uri getPhotoUrl() { - return photoUrl; - } - - public void setPhotoUrl(Uri photoUrl) { - this.photoUrl = photoUrl; - } - - public boolean hasPhoto() { - return photoUrl != null; - } + //Some data might not be used. + Position position, + @Nullable + Uri photoUrl +) { public record Id(long id) implements Parcelable { @NonNull diff --git a/src/main/java/de/dennisguse/opentracks/data/models/MarkerBuilder.java b/src/main/java/de/dennisguse/opentracks/data/models/MarkerBuilder.java new file mode 100644 index 000000000..8eb32a660 --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/data/models/MarkerBuilder.java @@ -0,0 +1,148 @@ +/* + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package de.dennisguse.opentracks.data.models; + +import android.net.Uri; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; + +import java.time.Instant; +import java.util.Objects; + +/** + * NOTE: A marker is indirectly (via it's {@link Position}) assigned to one {@link TrackPoint} via position.time. + * + * @author Leif Hendrik Wilden + * @author Rodrigo Damazio + */ +//TODO All data should be final; no default values. +public final class MarkerBuilder { + + private Marker.Id id; + private String name; + private String description; + private String category; + private String icon; + private final Track.Id trackId; + + //Some data might not be used. + private final Position position; + + private Uri photoUrl = null; + + @VisibleForTesting + public MarkerBuilder(@Nullable Track.Id trackId, @NonNull TrackPoint trackPoint) { + this.id = null; + this.trackId = trackId; + this.name = ""; + this.description = ""; + this.category = ""; + this.icon = ""; + this.photoUrl = null; + + if (!trackPoint.hasLocation()) + throw new RuntimeException("Marker requires a trackpoint with a location."); + + this.position = trackPoint.getPosition(); + } + + public MarkerBuilder(@Nullable Track.Id trackId, @NonNull TrackPoint trackPoint, String name, String description, String category, String icon, Uri photoUrl) { + this(trackId, trackPoint); + this.name = name; + this.description = description; + this.category = category; + this.icon = icon; + this.photoUrl = photoUrl; + } + + public MarkerBuilder(Marker marker) { + this.id = marker.id(); + this.trackId = marker.trackId(); + this.name = marker.name(); + this.description = marker.description(); + this.category = marker.category(); + this.icon = marker.icon(); + this.position = marker.position(); + this.photoUrl = marker.photoUrl(); + } + + /** + * May be null if the Marker was not loaded from the database. + */ + @Nullable + public Marker.Id getId() { + return id; + } + + //TODO Remove + @VisibleForTesting + @Deprecated + public void setId(Marker.Id id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setCategory(String category) { + this.category = category; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public Track.Id getTrackId() { + return trackId; + } + + public Uri getPhotoUrl() { + return photoUrl; + } + + public void setPhotoUrl(Uri photoUrl) { + this.photoUrl = photoUrl; + } + + public boolean hasPhoto() { + return photoUrl != null; + } + + public Marker getMarker() { + return new Marker( + id, + trackId, + name, + description, + category, + icon, + position, + photoUrl + ); + } +} diff --git a/src/main/java/de/dennisguse/opentracks/data/tables/MarkerColumns.java b/src/main/java/de/dennisguse/opentracks/data/tables/MarkerColumns.java index 2d3065f46..f9a4e5f8f 100644 --- a/src/main/java/de/dennisguse/opentracks/data/tables/MarkerColumns.java +++ b/src/main/java/de/dennisguse/opentracks/data/tables/MarkerColumns.java @@ -39,13 +39,14 @@ public interface MarkerColumns extends BaseColumns { String NAME = "name"; // marker name String DESCRIPTION = "description"; // marker description String CATEGORY = "category"; // marker category + @Deprecated //TODO Remove: it is always: position String ICON = "icon"; // marker icon String TRACKID = "trackid"; // track id String LONGITUDE = "longitude"; // longitude String LATITUDE = "latitude"; // latitude String TIME = "time"; // time String ALTITUDE = "elevation"; // altitude //TODO RENAME column - String ACCURACY = "accuracy"; // accuracy + String HORIZONTAL_ACCURACY = "accuracy"; // accuracy String BEARING = "bearing"; // bearing String PHOTOURL = "photoUrl"; // url for the photo @@ -61,7 +62,7 @@ public interface MarkerColumns extends BaseColumns { + LATITUDE + " INTEGER, " + TIME + " INTEGER, " + ALTITUDE + " FLOAT, " - + ACCURACY + " FLOAT, " + + HORIZONTAL_ACCURACY + " FLOAT, " + BEARING + " FLOAT, " + PHOTOURL + " TEXT, " + "FOREIGN KEY (" + TRACKID + ") REFERENCES " + TracksColumns.TABLE_NAME + "(" + TracksColumns._ID + ") ON UPDATE CASCADE ON DELETE CASCADE" diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java index c977c34f4..e1a9d1af4 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/GPXTrackExporter.java @@ -250,14 +250,14 @@ public class GPXTrackExporter implements TrackExporter { } private void writeMarker(ZoneOffset zoneOffset, Marker marker) { - printWriter.println(""); - if (marker.hasAltitude()) { - printWriter.println("" + ALTITUDE_FORMAT.format(marker.getAltitude().toM()) + ""); + printWriter.println(""); + if (marker.position().hasAltitude()) { + printWriter.println("" + ALTITUDE_FORMAT.format(marker.position().altitude().toM()) + ""); } - printWriter.println(""); - printWriter.println("" + StringUtils.formatCData(marker.getName()) + ""); - printWriter.println("" + StringUtils.formatCData(marker.getDescription()) + ""); - printWriter.println("" + StringUtils.formatCData(marker.getCategory()) + ""); //TODO This is localized; may be better to export in English only. See #1608 + printWriter.println(""); + printWriter.println("" + StringUtils.formatCData(marker.name()) + ""); + printWriter.println("" + StringUtils.formatCData(marker.description()) + ""); + printWriter.println("" + StringUtils.formatCData(marker.category()) + ""); //TODO This is localized; may be better to export in English only. See #1608 printWriter.println(""); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java index 48d5744d8..40a7a5153 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMLTrackExporter.java @@ -266,11 +266,11 @@ public class KMLTrackExporter implements TrackExporter { } private void writeMarker(Marker marker, ZoneOffset zoneOffset) { - boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, marker.getTrackId(), marker.getPhotoUrl()) != null; - if (marker.hasPhoto() && exportPhotos && existsPhoto) { + boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, marker.trackId(), marker.photoUrl()) != null; + if (marker.photoUrl() != null && exportPhotos && existsPhoto) { writePhotoOverlay(marker, zoneOffset); } else { - writePlacemark(marker.getName(), marker.getCategory(), marker.getDescription(), marker.getPosition(), marker.getTime(), zoneOffset); + writePlacemark(marker.name(), marker.category(), marker.description(), marker.position(), marker.position().time(), zoneOffset); } } @@ -428,17 +428,17 @@ public class KMLTrackExporter implements TrackExporter { private void writePhotoOverlay(Marker marker, ZoneOffset zoneOffset) { printWriter.println(""); - printWriter.println("" + StringUtils.formatCData(marker.getName()) + ""); - printWriter.println("" + StringUtils.formatCData(marker.getDescription()) + ""); + printWriter.println("" + StringUtils.formatCData(marker.name()) + ""); + printWriter.println("" + StringUtils.formatCData(marker.description()) + ""); printWriter.print(""); - printWriter.print("" + marker.getPosition().longitude() + ""); - printWriter.print("" + marker.getPosition().latitude() + ""); + printWriter.print("" + marker.position().longitude() + ""); + printWriter.print("" + marker.position().latitude() + ""); printWriter.print("20"); printWriter.print("90"); printWriter.println(""); - printWriter.println("" + getTime(zoneOffset, marker.getTime()) + ""); + printWriter.println("" + getTime(zoneOffset, marker.position().time()) + ""); printWriter.println("#" + MARKER_STYLE + ""); - writeTypeLocalized(marker.getCategory()); + writeTypeLocalized(marker.category()); if (exportPhotos) { printWriter.println("" + KMZTrackExporter.buildKmzImageFilePath(marker) + ""); @@ -452,7 +452,7 @@ public class KMLTrackExporter implements TrackExporter { printWriter.print("45"); printWriter.println(""); printWriter.println(""); - printWriter.println("" + getCoordinates(marker.getPosition(), ",") + ""); + printWriter.println("" + getCoordinates(marker.position(), ",") + ""); printWriter.println(""); printWriter.println(""); } diff --git a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java index 35ccc2053..0b1a11d64 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/exporter/KMZTrackExporter.java @@ -95,8 +95,8 @@ public class KMZTrackExporter implements TrackExporter { if (Thread.interrupted()) throw new InterruptedException(); Marker marker = markerIterator.next(); - if (marker.hasPhoto()) { - Uri uriPhoto = marker.getPhotoUrl(); + if (marker.photoUrl() != null) { + Uri uriPhoto = marker.photoUrl(); boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.id(), uriPhoto) != null; if (existsPhoto) { addImage(context, zipOutputStream, uriPhoto, marker); @@ -135,8 +135,8 @@ public class KMZTrackExporter implements TrackExporter { * Builds and returns the path for the image that will be saved inside KMZ_IMAGES_DIR for the marker. */ public static String buildKmzImageFilePath(Marker marker) { - String ext = FileUtils.getExtension(marker.getPhotoUrl()); + String ext = FileUtils.getExtension(marker.photoUrl()); ext = ext == null ? "" : "." + ext; - return KMZ_IMAGES_DIR + File.separatorChar + FileUtils.sanitizeFileName(marker.getId().id() + ext); + return KMZ_IMAGES_DIR + File.separatorChar + FileUtils.sanitizeFileName(marker.id().id() + ext); } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java index d53f869aa..7f3ee85a2 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java @@ -34,6 +34,7 @@ import java.util.Locale; import de.dennisguse.opentracks.data.models.Altitude; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Track; @@ -429,22 +430,16 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac Log.w(TAG, "Marker with invalid coordinates ignored: " + trackPoint.getPosition()); return; } - Marker marker = new Marker(null, trackPoint); - - if (name != null) { - marker.setName(name); - } - if (description != null) { - marker.setDescription(description); - } - if (markerType != null) { - marker.setCategory(markerType); - } - - if (photoUrl != null) { - marker.setPhotoUrl(photoUrl); - } - markers.add(marker); + markers.add(new Marker( + null, + null, + name != null ? name : "", + description != null ? description : "", + markerType != null ? markerType : "", + null, + trackPoint.getPosition(), + photoUrl + )); } private String createErrorMessage(String message) { diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java index 90422814a..07cd7fc98 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java @@ -35,6 +35,7 @@ import java.util.Locale; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Track; @@ -263,12 +264,16 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac } position = position.with(whenList.get(0)); - Marker marker = new Marker(null, new TrackPoint(TrackPoint.Type.TRACKPOINT, position)); //TODO Creating marker without need - marker.setName(name != null ? name : ""); - marker.setDescription(description != null ? description : ""); - marker.setCategory(activityTypeLocalized != null ? activityTypeLocalized : ""); - marker.setPhotoUrl(photoUrl); - markers.add(marker); + markers.add(new Marker( + null, + null, + name != null ? name : "", + description != null ? description : "", + activityTypeLocalized != null ? activityTypeLocalized : "", + null, + position, + photoUrl + )); name = null; description = null; diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java index 039c58275..dfe09e5dc 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMZTrackImporter.java @@ -36,6 +36,7 @@ import java.util.zip.ZipInputStream; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.FileUtils; @@ -191,8 +192,8 @@ public class KMZTrackImporter { List photosName = new ArrayList<>(); try (AutoCloseableIterator markerIterator = new ContentProviderUtils(context).getMarkerIterator(trackId)) { markerIterator.forEachRemaining(marker -> { - if (marker.hasPhoto()) { - String photoUrl = Uri.decode(marker.getPhotoUrl().toString()); //TODO Why Uri.decode()? + if (marker.photoUrl() != null) { + String photoUrl = Uri.decode(marker.photoUrl().toString()); //TODO Why Uri.decode()? photosName.add(photoUrl.substring(photoUrl.lastIndexOf(File.separatorChar) + 1)); } }); diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java index 726471d21..0a733be68 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java @@ -23,6 +23,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.ActivityType; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackBuilder; @@ -58,7 +59,7 @@ public class TrackImporter { // Current track private TrackData trackData; private final List trackPoints = new LinkedList<>(); - private final List markers = new LinkedList<>(); + private final List markers = new LinkedList<>(); public TrackImporter(Context context, ContentProviderUtils contentProviderUtils, Distance maxRecordingDistance, boolean preventReimport) { this.context = context; @@ -86,7 +87,7 @@ public class TrackImporter { } void addMarkers(List markers) { - this.markers.addAll(markers); + this.markers.addAll(markers.stream().map(MarkerBuilder::new).toList()); } void setTrackData(Context context, String name, String uuid, String description, String activityTypeLocalized, String activityTypeId, @Nullable ZoneOffset zoneOffset) { @@ -165,10 +166,8 @@ public class TrackImporter { // Store Markers updateMarkers(trackId); - for (Marker marker : markers) - marker.setTrackId(trackId); //TODO Should happen in bulkInsertMarkers - contentProviderUtils.bulkInsertMarkers(markers, trackId); + contentProviderUtils.bulkInsertMarkers(markers.stream().map(it -> it.getMarker()).toList(), trackId); //Clear up. trackPoints.clear(); diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index dc3b6dc73..82ab0e41a 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -37,6 +37,7 @@ import java.time.Duration; import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.sensors.GpsStatusValue; @@ -249,7 +250,16 @@ public class TrackRecordingService extends Service implements TrackPointCreator. if (trackPoint == null) { return null; } - Marker marker = new Marker(recordingStatus.trackId(), trackPoint); + Marker marker = new Marker( + null, + recordingStatus.trackId(), + "", + "", + "", + "", + trackPoint.getPosition(), + null + ); return new ContentProviderUtils(this).insertMarker(marker); } diff --git a/src/main/java/de/dennisguse/opentracks/share/ShareUtils.java b/src/main/java/de/dennisguse/opentracks/share/ShareUtils.java index b0c91acbd..d55b92978 100644 --- a/src/main/java/de/dennisguse/opentracks/share/ShareUtils.java +++ b/src/main/java/de/dennisguse/opentracks/share/ShareUtils.java @@ -94,14 +94,14 @@ public class ShareUtils { Log.e(TAG, "MarkerId " + markerId.id() + " could not be resolved."); continue; } - if (marker.getPhotoUrl() == null) { + if (marker.photoUrl() == null) { Log.e(TAG, "MarkerId " + markerId.id() + " has no picture."); continue; } - mime = context.getContentResolver().getType(marker.getPhotoUrl()); + mime = context.getContentResolver().getType(marker.photoUrl()); - uris.add(marker.getPhotoUrl()); + uris.add(marker.photoUrl()); } if (uris.isEmpty()) { diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java index 563d2f0be..8085e3598 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailActivity.java @@ -67,14 +67,14 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); Marker marker = contentProviderUtils.getMarker(markerId); - markerAutoCloseableIterator = contentProviderUtils.getMarkerIterator(marker.getTrackId()); + markerAutoCloseableIterator = contentProviderUtils.getMarkerIterator(marker.trackId()); if (markerAutoCloseableIterator == null) { finish(); } int markerIndex = -1; while (markerAutoCloseableIterator.hasNext()) { - if (markerId.equals(markerAutoCloseableIterator.next().getId())) { + if (markerId.equals(markerAutoCloseableIterator.next().id())) { markerIndex = markerAutoCloseableIterator.getPosition(); break; } @@ -124,7 +124,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark @NonNull public Fragment createFragment(int position) { markerAutoCloseableIterator.moveToPosition(position); - return MarkerDetailFragment.newInstance(markerAutoCloseableIterator.next().getId()); + return MarkerDetailFragment.newInstance(markerAutoCloseableIterator.next().id()); } @Override @@ -135,7 +135,7 @@ public class MarkerDetailActivity extends AbstractActivity implements DeleteMark @Nullable public CharSequence getPageTitle(int position) { markerAutoCloseableIterator.moveToPosition(position); - return getString(R.string.marker_detail_title, position + 1, getItemCount(), markerAutoCloseableIterator.next().getName()); + return getString(R.string.marker_detail_title, position + 1, getItemCount(), markerAutoCloseableIterator.next().name()); } } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailFragment.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailFragment.java index f9caf559e..cf35b93ec 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailFragment.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerDetailFragment.java @@ -111,8 +111,8 @@ public class MarkerDetailFragment extends Fragment { } if (item.getItemId() == R.id.marker_detail_share) { - if (marker.hasPhoto()) { - Intent intent = ShareUtils.newShareFileIntent(getContext(), marker.getId()); + if (marker.photoUrl() != null) { + Intent intent = ShareUtils.newShareFileIntent(getContext(), marker.id()); intent = Intent.createChooser(intent, null); startActivity(intent); } @@ -180,15 +180,15 @@ public class MarkerDetailFragment extends Fragment { } private void updateUi() { - if (marker.hasPhoto()) { - viewBinding.markerDetailMarkerPhoto.setImageURI(marker.getPhotoUrl()); + if (marker.photoUrl() != null) { + viewBinding.markerDetailMarkerPhoto.setImageURI(marker.photoUrl()); } else { viewBinding.markerDetailMarkerPhoto.setImageDrawable(MarkerUtils.getDefaultPhoto(getContext())); } - viewBinding.markerDetailMarkerCategory.setText(StringUtils.getCategory(marker.getCategory())); - viewBinding.markerDetailMarkerDescription.setText(marker.getDescription()); + viewBinding.markerDetailMarkerCategory.setText(StringUtils.getCategory(marker.category())); + viewBinding.markerDetailMarkerDescription.setText(marker.description()); - viewBinding.markerDetailMarkerLocation.setText(StringUtils.formatCoordinate(getContext(), marker.getPosition())); + viewBinding.markerDetailMarkerLocation.setText(StringUtils.formatCoordinate(getContext(), marker.position())); } } diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java index 10bfce2ae..f98e51480 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditActivity.java @@ -47,6 +47,7 @@ import java.time.Instant; import de.dennisguse.opentracks.AbstractActivity; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Position; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; @@ -181,11 +182,11 @@ public class MarkerEditActivity extends AbstractActivity { private void loadMarkerData(Marker data) { marker = data; - viewBinding.markerEditName.setText(marker.getName()); - viewBinding.markerEditMarkerType.setText(marker.getCategory()); - viewBinding.markerEditDescription.setText(marker.getDescription()); - if (marker.hasPhoto()) { - setMarkerImageView(marker.getPhotoUrl()); + viewBinding.markerEditName.setText(marker.name()); + viewBinding.markerEditMarkerType.setText(marker.category()); + viewBinding.markerEditDescription.setText(marker.description()); + if (marker.photoUrl() != null) { + setMarkerImageView(marker.photoUrl()); } else { viewBinding.markerEditPhoto.setImageDrawable(null); } @@ -247,7 +248,7 @@ public class MarkerEditActivity extends AbstractActivity { * If a photo is set then one's options are shown, otherwise another ones are shown. */ private void hideAndShowOptions() { - boolean isPhotoSet = (marker != null && marker.hasPhoto()); + boolean isPhotoSet = (marker != null && marker.photoUrl() != null); if (insertPhotoMenuItem != null && insertGalleryImgMenuItem != null) { insertPhotoMenuItem.setVisible(!isPhotoSet); insertGalleryImgMenuItem.setVisible(!isPhotoSet); @@ -259,7 +260,7 @@ public class MarkerEditActivity extends AbstractActivity { * Returns the trackId; either from track or marker. */ private Track.Id getTrackId() { - return trackId == null ? marker.getTrackId() : trackId; + return trackId == null ? marker.trackId() : trackId; } private void setMarkerImageView(@NonNull Uri uri) { diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java index fa2f4685c..a6a55ff91 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerEditViewModel.java @@ -20,6 +20,7 @@ import java.util.NoSuchElementException; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.Marker; +import de.dennisguse.opentracks.data.models.MarkerBuilder; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.util.FileUtils; @@ -40,8 +41,8 @@ public class MarkerEditViewModel extends AndroidViewModel { markerData = new MutableLiveData<>(); Marker marker = new ContentProviderUtils(getApplication()).getMarker(markerId); - if (marker.hasPhoto()) { - photoOriginalUri = marker.getPhotoUrl(); + if (marker.photoUrl() != null) { + photoOriginalUri = marker.photoUrl(); } markerData.postValue(marker); @@ -63,20 +64,20 @@ public class MarkerEditViewModel extends AndroidViewModel { return; } - File photoFile = MarkerUtils.getPhotoFileIfExists(getApplication(), markerData.getValue().getTrackId(), photoUri); + File photoFile = MarkerUtils.getPhotoFileIfExists(getApplication(), markerData.getValue().trackId(), photoUri); if (photoFile != null) { FileUtils.deleteDirectoryRecurse(photoFile); } } private void deletePhoto(Marker marker) { - if (marker.hasPhoto()) { - deletePhoto(marker.getPhotoUrl()); + if (marker.photoUrl() != null) { + deletePhoto(marker.photoUrl()); } } public void onPhotoDelete(String name, String category, String description) { - Marker marker = getMarker(); + MarkerBuilder marker = new MarkerBuilder(getMarker()); if (marker.hasPhoto()) { if (!marker.getPhotoUrl().equals(photoOriginalUri)) { deletePhoto(marker.getPhotoUrl()); @@ -85,21 +86,21 @@ public class MarkerEditViewModel extends AndroidViewModel { marker.setName(name); marker.setCategory(category); marker.setDescription(description); - markerData.postValue(marker); + markerData.postValue(marker.getMarker()); } } public void onNewCameraPhoto(@NonNull Uri photoUri, String name, String category, String description) { - Marker marker = getMarker(); + MarkerBuilder marker = new MarkerBuilder(getMarker()); marker.setPhotoUrl(photoUri); marker.setName(name); marker.setCategory(category); marker.setDescription(description); - markerData.postValue(marker); + markerData.postValue(marker.getMarker()); } public void onNewGalleryPhoto(@NonNull Uri srcUri, String name, String category, String description) { - Marker marker = getMarker(); + MarkerBuilder marker = new MarkerBuilder(getMarker()); try (ParcelFileDescriptor parcelFd = getApplication().getContentResolver().openFileDescriptor(srcUri, "r")) { FileDescriptor srcFd = parcelFd.getFileDescriptor(); @@ -111,7 +112,8 @@ public class MarkerEditViewModel extends AndroidViewModel { marker.setName(name); marker.setCategory(category); marker.setDescription(description); - markerData.postValue(marker); + + markerData.postValue(marker.getMarker()); } catch (IOException e) { Log.e(TAG, e.getMessage()); Toast.makeText(getApplication(), R.string.marker_add_canceled, Toast.LENGTH_LONG).show(); @@ -119,15 +121,15 @@ public class MarkerEditViewModel extends AndroidViewModel { } public void onDone(String name, String category, String description) { - Marker marker = getMarker(); + MarkerBuilder marker = new MarkerBuilder(getMarker()); marker.setName(name); marker.setCategory(category); marker.setDescription(description); if (marker.getId() == null) { - new ContentProviderUtils(getApplication()).insertMarker(marker); + new ContentProviderUtils(getApplication()).insertMarker(marker.getMarker()); } else { - new ContentProviderUtils(getApplication()).updateMarker(getApplication(), marker); + new ContentProviderUtils(getApplication()).updateMarker(getApplication(), marker.getMarker()); } if (photoOriginalUri != null && (!marker.hasPhoto() || !photoOriginalUri.equals(marker.getPhotoUrl()))) { @@ -143,7 +145,15 @@ public class MarkerEditViewModel extends AndroidViewModel { String name = getApplication().getString(R.string.marker_name_format, nextMarkerNumber + 1); String icon = getApplication().getString(R.string.marker_icon_url); - Marker marker = new Marker(trackId, trackPoint, name, "", "", icon, null); + Marker marker = new Marker( + null, + trackId, + name, + "", + icon, + "", + trackPoint.getPosition(), + null); if (markerData == null) { markerData = new MutableLiveData<>(); @@ -158,7 +168,7 @@ public class MarkerEditViewModel extends AndroidViewModel { // it's new marker -> clean all photos. deletePhoto(marker); deletePhoto(photoOriginalUri); - } else if (photoOriginalUri == null || (marker.hasPhoto() && !marker.getPhotoUrl().equals(photoOriginalUri))) { + } else if (photoOriginalUri == null || (marker.photoUrl() != null && !marker.photoUrl().equals(photoOriginalUri))) { // it's an edit marker -> delete photo if it was empty or it was changed (leaving the original in that case). deletePhoto(marker); } diff --git a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerListAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerListAdapter.java index fc8839ba1..e2dc990c9 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerListAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/ui/markers/MarkerListAdapter.java @@ -137,7 +137,7 @@ public class MarkerListAdapter extends RecyclerView.Adapter