diff --git a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java index 06ee6689be..1e357c7f04 100644 --- a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java +++ b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java @@ -112,7 +112,7 @@ public class GPXUtilities { } public interface GPXExtensionsReader { - public boolean readExtensions(GPXFile res, XmlPullParser parser) throws Exception; + public boolean readExtensions(GPXFile res, XmlPullParser parser) throws IOException, XmlPullParserException; } public static class GPXExtensions { @@ -1965,7 +1965,7 @@ public class GPXUtilities { } } - private static void writeNotNullText(XmlSerializer serializer, String tag, String value) throws IOException { + public static void writeNotNullText(XmlSerializer serializer, String tag, String value) throws IOException { if (value != null) { serializer.startTag(null, tag); serializer.text(value); @@ -2085,7 +2085,7 @@ public class GPXUtilities { } } - private static String readText(XmlPullParser parser, String key) throws XmlPullParserException, IOException { + public static String readText(XmlPullParser parser, String key) throws XmlPullParserException, IOException { int tok; StringBuilder text = null; while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) { @@ -2146,36 +2146,36 @@ public class GPXUtilities { return time; } - public static GPXFile loadGPXFile(File f) { + public static GPXFile loadGPXFile(File file) { + return loadGPXFile(file, null); + } + + public static GPXFile loadGPXFile(File file, GPXExtensionsReader extensionsReader) { FileInputStream fis = null; try { - fis = new FileInputStream(f); - GPXFile file = loadGPXFile(fis); - file.path = f.getAbsolutePath(); - file.modifiedTime = f.lastModified(); + fis = new FileInputStream(file); + GPXFile gpxFile = loadGPXFile(fis, extensionsReader); + gpxFile.path = file.getAbsolutePath(); + gpxFile.modifiedTime = file.lastModified(); - try { - fis.close(); - } catch (IOException e) { - } - return file; + Algorithms.closeStream(fis); + return gpxFile; } catch (IOException e) { - GPXFile res = new GPXFile(null); - res.path = f.getAbsolutePath(); - log.error("Error reading gpx " + res.path, e); //$NON-NLS-1$ - res.error = e; - return res; + GPXFile gpxFile = new GPXFile(null); + gpxFile.path = file.getAbsolutePath(); + log.error("Error reading gpx " + gpxFile.path, e); //$NON-NLS-1$ + gpxFile.error = e; + return gpxFile; } finally { - try { - if (fis != null) - fis.close(); - } catch (IOException ignore) { - // ignore - } + Algorithms.closeStream(fis); } } - public static GPXFile loadGPXFile(InputStream f) { + public static GPXFile loadGPXFile(InputStream stream) { + return loadGPXFile(stream, null); + } + + public static GPXFile loadGPXFile(InputStream stream, GPXExtensionsReader extensionsReader) { GPXFile gpxFile = new GPXFile(null); SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT, Locale.US); format.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -2183,7 +2183,7 @@ public class GPXUtilities { formatMillis.setTimeZone(TimeZone.getTimeZone("UTC")); try { XmlPullParser parser = PlatformUtil.newXMLPullParser(); - parser.setInput(getUTF8Reader(f)); + parser.setInput(getUTF8Reader(stream)); Track routeTrack = new Track(); TrkSegment routeTrackSegment = new TrkSegment(); routeTrack.segments.add(routeTrackSegment); @@ -2231,17 +2231,19 @@ public class GPXUtilities { break; default: - Map values = readTextMap(parser, tag); - if (values.size() > 0) { - for (Entry entry : values.entrySet()) { - String t = entry.getKey().toLowerCase(); - String value = entry.getValue(); - parse.getExtensionsToWrite().put(t, value); - if (tag.equals("speed") && parse instanceof WptPt) { - try { - ((WptPt) parse).speed = Float.parseFloat(value); - } catch (NumberFormatException e) { - log.debug(e.getMessage(), e); + if (extensionsReader == null || !extensionsReader.readExtensions(gpxFile, parser)) { + Map values = readTextMap(parser, tag); + if (values.size() > 0) { + for (Entry entry : values.entrySet()) { + String t = entry.getKey().toLowerCase(); + String value = entry.getValue(); + parse.getExtensionsToWrite().put(t, value); + if (tag.equals("speed") && parse instanceof WptPt) { + try { + ((WptPt) parse).speed = Float.parseFloat(value); + } catch (NumberFormatException e) { + log.debug(e.getMessage(), e); + } } } } diff --git a/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java b/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java index ab12baf5e1..d912e61dc9 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/Algorithms.java @@ -2,8 +2,8 @@ package net.osmand.util; import net.osmand.IProgress; import net.osmand.PlatformUtil; -import net.osmand.router.RouteColorize; import net.osmand.data.LatLon; +import net.osmand.router.RouteColorize; import org.apache.commons.logging.Log; import org.xmlpull.v1.XmlPullParser; @@ -26,8 +26,8 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -298,17 +298,25 @@ public class Algorithms { } public static Set decodeStringSet(String s) { - if (isEmpty(s)) { - return Collections.emptySet(); - } - return new HashSet<>(Arrays.asList(s.split(CHAR_TOSPLIT + ""))); + return decodeStringSet(s, String.valueOf(CHAR_TOSPLIT)); } public static String encodeStringSet(Set set) { + return encodeStringSet(set, String.valueOf(CHAR_TOSPLIT)); + } + + public static Set decodeStringSet(String s, String split) { + if (isEmpty(s)) { + return Collections.emptySet(); + } + return new LinkedHashSet<>(Arrays.asList(s.split(split))); + } + + public static String encodeStringSet(Set set, String split) { if (set != null) { StringBuilder sb = new StringBuilder(); for (String s : set) { - sb.append(s).append(CHAR_TOSPLIT); + sb.append(s).append(split); } return sb.toString(); } diff --git a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java index 42cf1c0d2e..c7df9ea206 100644 --- a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java @@ -14,12 +14,13 @@ import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.WptPt; import net.osmand.PlatformUtil; import net.osmand.data.FavouritePoint; +import net.osmand.data.FavouritePoint.SpecialPointType; import net.osmand.data.LatLon; import net.osmand.plus.GeocodingLookupService.AddressLookupRequest; -import net.osmand.plus.mapmarkers.MapMarkersHelper; -import net.osmand.plus.mapmarkers.MapMarkersGroup; import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; import net.osmand.plus.api.SQLiteAPI.SQLiteCursor; +import net.osmand.plus.mapmarkers.ItineraryGroup; +import net.osmand.plus.mapmarkers.ItineraryHelper; import net.osmand.util.Algorithms; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; @@ -246,7 +247,7 @@ public class FavouritesDbHelper { }); } - public FavouritePoint getSpecialPoint(FavouritePoint.SpecialPointType pointType) { + public FavouritePoint getSpecialPoint(SpecialPointType pointType) { for (FavouritePoint fp : cachedFavoritePoints) { if (fp.getSpecialPointType() == pointType) { return fp; @@ -280,16 +281,16 @@ public class FavouritesDbHelper { } private void runSyncWithMarkers(FavoriteGroup favGroup) { - MapMarkersHelper helper = context.getMapMarkersHelper(); - MapMarkersGroup group = helper.getMarkersGroup(favGroup); + ItineraryHelper helper = context.getItineraryHelper(); + ItineraryGroup group = helper.getMarkersGroup(favGroup); if (group != null) { helper.runSynchronization(group); } } private boolean removeFromMarkers(FavoriteGroup favGroup) { - MapMarkersHelper helper = context.getMapMarkersHelper(); - MapMarkersGroup group = helper.getMarkersGroup(favGroup); + ItineraryHelper helper = context.getItineraryHelper(); + ItineraryGroup group = helper.getMarkersGroup(favGroup); if (group != null) { helper.removeMarkersGroup(group); return true; @@ -298,7 +299,7 @@ public class FavouritesDbHelper { } private void addToMarkers(FavoriteGroup favGroup) { - MapMarkersHelper helper = context.getMapMarkersHelper(); + ItineraryHelper helper = context.getItineraryHelper(); helper.addOrEnableGroup(favGroup); } @@ -580,7 +581,7 @@ public class FavouritesDbHelper { } } - private void backup(File backupFile, File externalFile) { + public static void backup(File backupFile, File externalFile) { try { File f = new File(backupFile.getParentFile(), backupFile.getName()); BZip2CompressorOutputStream out = new BZip2CompressorOutputStream(new FileOutputStream(f)); @@ -635,7 +636,11 @@ public class FavouritesDbHelper { } public File getBackupFile() { - File fld = new File(context.getAppPath(null), BACKUP_FOLDER); + return getBackupFile(context, "favourites_bak_"); + } + + public static File getBackupFile(OsmandApplication app, String fileName) { + File fld = new File(app.getAppPath(null), BACKUP_FOLDER); if (!fld.exists()) { fld.mkdirs(); } @@ -648,7 +653,7 @@ public class FavouritesDbHelper { if (back < 10) { backPrefix = "0" + backPrefix; } - File bak = new File(fld, "favourites_bak_" + backPrefix + ".gpx.bz2"); + File bak = new File(fld, fileName + backPrefix + ".gpx.bz2"); if (!bak.exists()) { return bak; } else if (bak.lastModified() < firstModifiedMin) { @@ -845,9 +850,7 @@ public class FavouritesDbHelper { } for (WptPt p : res.getPoints()) { FavouritePoint fp = FavouritePoint.fromWpt(p, context); - if (fp != null) { - points.put(getKey(fp), fp); - } + points.put(getKey(fp), fp); } return true; } @@ -959,7 +962,7 @@ public class FavouritesDbHelper { public void onUpgrade(SQLiteConnection db, int oldVersion, int newVersion) { if (oldVersion == 1) { db.execSQL("ALTER TABLE " + FAVOURITE_TABLE_NAME + " ADD " + FAVOURITE_COL_CATEGORY + " text"); - db.execSQL("UPDATE " + FAVOURITE_TABLE_NAME + " SET category = ?", new Object[]{""}); //$NON-NLS-1$ //$NON-NLS-2$ + db.execSQL("UPDATE " + FAVOURITE_TABLE_NAME + " SET category = ?", new Object[] {""}); //$NON-NLS-1$ //$NON-NLS-2$ } } diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/ItineraryHelper.java b/OsmAnd/src/net/osmand/plus/mapmarkers/ItineraryHelper.java index 9fd582ca03..f25779e947 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/ItineraryHelper.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/ItineraryHelper.java @@ -5,10 +5,7 @@ import android.os.AsyncTask; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import net.osmand.FileUtils; -import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.WptPt; import net.osmand.IndexConstants; @@ -17,14 +14,13 @@ import net.osmand.data.FavouritePoint; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; -import net.osmand.plus.GPXDatabase; +import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GeocodingLookupService; import net.osmand.plus.GeocodingLookupService.AddressLookupRequest; import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.Version; import net.osmand.plus.wikivoyage.data.TravelArticle; import net.osmand.plus.wikivoyage.data.TravelHelper; import net.osmand.util.Algorithms; @@ -35,26 +31,20 @@ import org.apache.commons.logging.Log; import java.io.File; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; -import java.util.TimeZone; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import static net.osmand.GPXUtilities.GPX_TIME_FORMAT; import static net.osmand.data.PointDescription.POINT_TYPE_MAP_MARKER; -public class MapMarkersHelper { +public class ItineraryHelper { public static final int MAP_MARKERS_COLORS_COUNT = 7; @@ -65,24 +55,22 @@ public class MapMarkersHelper { public static final int BY_DATE_ADDED_ASC = 4; - public static final String VISITED_DATE = "visited_date"; - public static final String CREATION_DATE = "creation_date"; - - private static final Log LOG = PlatformUtil.getLog(MapMarkersHelper.class); + private static final Log LOG = PlatformUtil.getLog(ItineraryHelper.class); @Retention(RetentionPolicy.SOURCE) @IntDef({BY_NAME, BY_DISTANCE_DESC, BY_DISTANCE_ASC, BY_DATE_ADDED_DESC, BY_DATE_ADDED_ASC}) public @interface MapMarkersSortByDef { } - private OsmandApplication ctx; + private OsmandApplication app; private MapMarkersDbHelper markersDbHelper; + private ItinerarySaveHelper saveHelper; private ExecutorService executorService = Executors.newSingleThreadExecutor(); private List mapMarkers = new ArrayList<>(); private List mapMarkersHistory = new ArrayList<>(); - private List mapMarkersGroups = new ArrayList<>(); + private List itineraryGroups = new ArrayList<>(); private List listeners = new ArrayList<>(); private Set syncListeners = new HashSet<>(); @@ -97,26 +85,31 @@ public class MapMarkersHelper { return mapMarkersHistory; } - public List getMapMarkersGroups() { - return mapMarkersGroups; + public List getItineraryGroups() { + return itineraryGroups; } public boolean isStartFromMyLocation() { - return ctx.getSettings().ROUTE_MAP_MARKERS_START_MY_LOC.get(); + return app.getSettings().ROUTE_MAP_MARKERS_START_MY_LOC.get(); } public void setStartFromMyLocation(boolean startFromMyLocation) { - ctx.getSettings().ROUTE_MAP_MARKERS_START_MY_LOC.set(startFromMyLocation); + app.getSettings().ROUTE_MAP_MARKERS_START_MY_LOC.set(startFromMyLocation); } public MarkersPlanRouteContext getPlanRouteContext() { return planRouteContext; } - public MapMarkersHelper(OsmandApplication ctx) { - this.ctx = ctx; - markersDbHelper = ctx.getMapMarkersDbHelper(); - planRouteContext = new MarkersPlanRouteContext(ctx); + public ItinerarySaveHelper getSaveHelper() { + return saveHelper; + } + + public ItineraryHelper(OsmandApplication app) { + this.app = app; + saveHelper = new ItinerarySaveHelper(app, this); + markersDbHelper = app.getMapMarkersDbHelper(); + planRouteContext = new MarkersPlanRouteContext(app); markersDbHelper.removeDisabledGroups(); loadMarkers(); loadGroups(); @@ -133,7 +126,7 @@ public class MapMarkersHelper { sortMarkers(markersHistory, true, BY_DATE_ADDED_DESC); addToMapMarkersHistoryList(markersHistory); - if (!ctx.isApplicationInitializing()) { + if (!app.isApplicationInitializing()) { lookupAddressAll(); } } @@ -152,13 +145,13 @@ public class MapMarkersHelper { } } - MapMarkersGroup noGroup = null; + ItineraryGroup noGroup = null; for (MapMarker marker : allMarkers) { - MapMarkersGroup group = groupsMap.get(marker.groupKey); + ItineraryGroup group = groupsMap.get(marker.groupKey); if (group == null) { if (noGroup == null) { - noGroup = new MapMarkersGroup(); + noGroup = new ItineraryGroup(); noGroup.setCreationDate(Long.MAX_VALUE); } noGroup.getMarkers().add(marker); @@ -170,7 +163,7 @@ public class MapMarkersHelper { } } - mapMarkersGroups = new ArrayList<>(groupsMap.values()); + itineraryGroups = new ArrayList<>(groupsMap.values()); if (noGroup != null) { sortMarkers(noGroup.getMarkers(), false, BY_DATE_ADDED_DESC); addToGroupsList(noGroup); @@ -178,13 +171,17 @@ public class MapMarkersHelper { sortGroups(); - for (MapMarkersGroup group : mapMarkersGroups) { + for (ItineraryGroup group : itineraryGroups) { updateGroup(group); } } + private void saveGroups() { + saveHelper.saveGroups(); + } + public void syncAllGroupsAsync() { - for (MapMarkersGroup gr : mapMarkersGroups) { + for (ItineraryGroup gr : itineraryGroups) { if (gr.getId() != null && gr.getName() != null) { runSynchronization(gr); } @@ -201,7 +198,7 @@ public class MapMarkersHelper { } private void lookupAddress(final MapMarker mapMarker) { - if (mapMarker != null && mapMarker.getOriginalPointDescription().isSearchingAddress(ctx)) { + if (mapMarker != null && mapMarker.getOriginalPointDescription().isSearchingAddress(app)) { cancelPointAddressRequests(mapMarker.point); AddressLookupRequest lookupRequest = new AddressLookupRequest(mapMarker.point, new GeocodingLookupService.OnAddressLookupResult() { @@ -209,7 +206,7 @@ public class MapMarkersHelper { public void geocodingDone(String address) { PointDescription pointDescription = mapMarker.getOriginalPointDescription(); if (Algorithms.isEmpty(address)) { - pointDescription.setName(PointDescription.getAddressNotFoundStr(ctx)); + pointDescription.setName(PointDescription.getAddressNotFoundStr(app)); } else { pointDescription.setName(address); } @@ -217,7 +214,7 @@ public class MapMarkersHelper { refreshMarker(mapMarker); } }, null); - ctx.getGeocodingLookupService().lookupAddress(lookupRequest); + app.getGeocodingLookupService().lookupAddress(lookupRequest); } } @@ -234,7 +231,7 @@ public class MapMarkersHelper { private void cancelPointAddressRequests(LatLon latLon) { if (latLon != null) { - ctx.getGeocodingLookupService().cancel(latLon); + app.getGeocodingLookupService().cancel(latLon); } } @@ -295,16 +292,16 @@ public class MapMarkersHelper { return sortByMode == BY_DISTANCE_DESC ? 1 : -1; } } else { - String n1 = mapMarker1.getName(ctx); - String n2 = mapMarker2.getName(ctx); + String n1 = mapMarker1.getName(app); + String n2 = mapMarker2.getName(app); return n1.compareToIgnoreCase(n2); } } }); } - public void runSynchronization(final @NonNull MapMarkersGroup group) { - ctx.runInUIThread(new Runnable() { + public void runSynchronization(final @NonNull ItineraryGroup group) { + app.runInUIThread(new Runnable() { @Override public void run() { new SyncGroupTask(group).executeOnExecutor(executorService); @@ -312,7 +309,7 @@ public class MapMarkersHelper { }); } - public MapMarkersGroup getMarkersGroup(GPXFile gpx) { + public ItineraryGroup getMarkersGroup(GPXFile gpx) { if (gpx == null || gpx.path == null) { return null; } @@ -334,9 +331,9 @@ public class MapMarkersHelper { return gr; } - public MapMarkersGroup addOrEnableGroup(@NonNull GPXFile file) { + public ItineraryGroup addOrEnableGroup(@NonNull GPXFile file) { updateGpxShowAsMarkers(new File(file.path)); - MapMarkersGroup gr = getMarkersGroup(file); + ItineraryGroup gr = getMarkersGroup(file); if (gr == null) { gr = createGPXMarkerGroup(new File(file.path)); addGroupInternally(gr); @@ -345,8 +342,8 @@ public class MapMarkersHelper { return gr; } - public MapMarkersGroup addOrEnableGroup(@NonNull FavoriteGroup group) { - MapMarkersGroup gr = getMarkersGroup(group); + public ItineraryGroup addOrEnableGroup(@NonNull FavoriteGroup group) { + ItineraryGroup gr = getMarkersGroup(group); if (gr == null) { gr = createFavMarkerGroup(group); addGroupInternally(gr); @@ -355,9 +352,9 @@ public class MapMarkersHelper { return gr; } - public void enableGroup(@NonNull MapMarkersGroup gr) { + public void enableGroup(@NonNull ItineraryGroup gr) { // check if group doesn't exist internally - if (!mapMarkersGroups.contains(gr)) { + if (!itineraryGroups.contains(gr)) { addGroupInternally(gr); } if (gr.isDisabled()) { @@ -366,21 +363,21 @@ public class MapMarkersHelper { runSynchronization(gr); } - private void addGroupInternally(MapMarkersGroup gr) { + private void addGroupInternally(ItineraryGroup gr) { markersDbHelper.addGroup(gr); addHistoryMarkersToGroup(gr); addToGroupsList(gr); } private void updateGpxShowAsMarkers(File file) { - GPXDatabase.GpxDataItem dataItem = ctx.getGpxDbHelper().getItem(file); + GpxDataItem dataItem = app.getGpxDbHelper().getItem(file); if (dataItem != null) { - ctx.getGpxDbHelper().updateShowAsMarkers(dataItem, true); + app.getGpxDbHelper().updateShowAsMarkers(dataItem, true); dataItem.setShowAsMarkers(true); } } - private void addHistoryMarkersToGroup(@NonNull MapMarkersGroup group) { + private void addHistoryMarkersToGroup(@NonNull ItineraryGroup group) { List historyMarkers = new ArrayList<>(mapMarkersHistory); for (MapMarker m : historyMarkers) { if (m.groupKey != null && group.getId() != null && m.groupKey.equals(group.getId())) { @@ -389,7 +386,7 @@ public class MapMarkersHelper { } } - public void removeMarkersGroup(MapMarkersGroup group) { + public void removeMarkersGroup(ItineraryGroup group) { if (group != null) { markersDbHelper.removeMarkersGroup(group.getId()); removeGroupActiveMarkers(group, false); @@ -397,7 +394,7 @@ public class MapMarkersHelper { } } - public void updateGroupDisabled(@NonNull MapMarkersGroup group, boolean disabled) { + public void updateGroupDisabled(@NonNull ItineraryGroup group, boolean disabled) { String id = group.getId(); if (id != null) { markersDbHelper.updateGroupDisabled(id, disabled); @@ -405,7 +402,7 @@ public class MapMarkersHelper { } } - public void updateGroupWptCategories(@NonNull MapMarkersGroup group, Set wptCategories) { + public void updateGroupWptCategories(@NonNull ItineraryGroup group, Set wptCategories) { String id = group.getId(); if (id != null) { group.setWptCategories(wptCategories); @@ -415,7 +412,7 @@ public class MapMarkersHelper { } } - private void removeGroupActiveMarkers(MapMarkersGroup group, boolean updateGroup) { + private void removeGroupActiveMarkers(ItineraryGroup group, boolean updateGroup) { if (group != null) { markersDbHelper.removeActiveMarkersFromGroup(group.getId()); removeFromMapMarkersList(group.getActiveMarkers()); @@ -429,26 +426,26 @@ public class MapMarkersHelper { } public void updateGroups() { - for (MapMarkersGroup group : mapMarkersGroups) { + for (ItineraryGroup group : itineraryGroups) { updateGroup(group); } } - public void updateGroup(MapMarkersGroup mapMarkersGroup) { - if (mapMarkersGroup.getId() == null || mapMarkersGroup.getName() == null) { + public void updateGroup(ItineraryGroup itineraryGroup) { + if (itineraryGroup.getId() == null || itineraryGroup.getName() == null) { return; } - createHeadersInGroup(mapMarkersGroup); - int historyMarkersCount = mapMarkersGroup.getHistoryMarkers().size(); - ShowHideHistoryButton showHideHistoryButton = mapMarkersGroup.getShowHideHistoryButton(); + createHeadersInGroup(itineraryGroup); + int historyMarkersCount = itineraryGroup.getHistoryMarkers().size(); + ShowHideHistoryButton showHideHistoryButton = itineraryGroup.getShowHideHistoryButton(); if (showHideHistoryButton != null) { if (historyMarkersCount == 0) { - mapMarkersGroup.setShowHideHistoryButton(null); + itineraryGroup.setShowHideHistoryButton(null); } } else if (historyMarkersCount > 0) { showHideHistoryButton = new ShowHideHistoryButton(); showHideHistoryButton.showHistory = false; - mapMarkersGroup.setShowHideHistoryButton(showHideHistoryButton); + itineraryGroup.setShowHideHistoryButton(showHideHistoryButton); } } @@ -456,6 +453,7 @@ public class MapMarkersHelper { for (MapMarker marker : markers) { addMarkerToGroup(marker); } + saveGroups(); } private void addMarkerToGroup(MapMarker marker) { @@ -500,10 +498,10 @@ public class MapMarkersHelper { } private void sortGroups() { - if (mapMarkersGroups.size() > 0) { - Collections.sort(mapMarkersGroups, new Comparator() { + if (itineraryGroups.size() > 0) { + Collections.sort(itineraryGroups, new Comparator() { @Override - public int compare(MapMarkersGroup group1, MapMarkersGroup group2) { + public int compare(ItineraryGroup group1, ItineraryGroup group2) { long t1 = group1.getCreationDate(); long t2 = group2.getCreationDate(); return (t1 > t2) ? -1 : ((t1 == t2) ? 0 : 1); @@ -544,13 +542,13 @@ public class MapMarkersHelper { } @NonNull - public List getGroupsForDisplayedGpx() { - List res = new ArrayList<>(); - List selectedGpxFiles = ctx.getSelectedGpxHelper().getSelectedGPXFiles(); + public List getGroupsForDisplayedGpx() { + List res = new ArrayList<>(); + List selectedGpxFiles = app.getSelectedGpxHelper().getSelectedGPXFiles(); for (SelectedGpxFile selected : selectedGpxFiles) { - MapMarkersGroup search = getMarkersGroup(selected.getGpxFile()); + ItineraryGroup search = getMarkersGroup(selected.getGpxFile()); if (search == null && selected.getGpxFile() != null && selected.getGpxFile().path != null) { - MapMarkersGroup group = createGPXMarkerGroup(new File(selected.getGpxFile().path)); + ItineraryGroup group = createGPXMarkerGroup(new File(selected.getGpxFile().path)); group.setDisabled(true); createHeadersInGroup(group); res.add(group); @@ -612,7 +610,7 @@ public class MapMarkersHelper { private List getMarkers() { List res = new ArrayList<>(mapMarkers); - if (ctx.getSettings().KEEP_PASSED_MARKERS_ON_MAP.get()) { + if (app.getSettings().KEEP_PASSED_MARKERS_ON_MAP.get()) { res.addAll(mapMarkersHistory); } return res; @@ -631,7 +629,7 @@ public class MapMarkersHelper { return null; } - private void addNewMarkerIfNeeded(@NonNull MapMarkersGroup group, + private void addNewMarkerIfNeeded(@NonNull ItineraryGroup group, @NonNull List groupMarkers, @NonNull LatLon latLon, @NonNull String name, @@ -868,18 +866,18 @@ public class MapMarkersHelper { public void addMapMarkers(@NonNull List points, @NonNull List historyNames, - @Nullable MapMarkersGroup group) { + @Nullable ItineraryGroup group) { addMarkers(points, historyNames, group, null, null, null); } private void addMarkers(@NonNull List points, @NonNull List historyNames, - @Nullable MapMarkersGroup group, + @Nullable ItineraryGroup group, @Nullable List favouritePoints, @Nullable List wptPts, @Nullable List mapObjNames) { if (points.size() > 0) { - ctx.getSettings().SHOW_MAP_MARKERS.set(true); + app.getSettings().SHOW_MAP_MARKERS.set(true); int colorIndex = -1; List addedMarkers = new ArrayList<>(); for (int i = 0; i < points.size(); i++) { @@ -895,7 +893,7 @@ public class MapMarkersHelper { pointDescription = historyName; } if (pointDescription.isLocation() && Algorithms.isEmpty(pointDescription.getName())) { - pointDescription.setName(PointDescription.getSearchAddressStr(ctx)); + pointDescription.setName(PointDescription.getSearchAddressStr(app)); } if (colorIndex == -1) { if (mapMarkers.size() > 0) { @@ -909,7 +907,7 @@ public class MapMarkersHelper { MapMarker marker = new MapMarker(point, pointDescription, colorIndex, false, 0); if (group != null) { - marker.id = group.getId() + marker.getName(ctx) + MapUtils.createShortLinkString(marker.point.getLatitude(), marker.point.getLongitude(), 15); + marker.id = group.getId() + marker.getName(app) + MapUtils.createShortLinkString(marker.point.getLatitude(), marker.point.getLongitude(), 15); if (markersDbHelper.getMarker(marker.id) != null) { continue; } @@ -984,7 +982,7 @@ public class MapMarkersHelper { } private void refreshMarker(final MapMarker marker) { - ctx.runInUIThread(new Runnable() { + app.runInUIThread(new Runnable() { @Override public void run() { for (MapMarkerChangedListener l : listeners) { @@ -995,7 +993,7 @@ public class MapMarkersHelper { } private void refresh() { - ctx.runInUIThread(new Runnable() { + app.runInUIThread(new Runnable() { @Override public void run() { for (MapMarkerChangedListener l : listeners) { @@ -1003,6 +1001,7 @@ public class MapMarkersHelper { } } }); + saveGroups(); } public List getMapMarkersFromDefaultGroups(boolean history) { @@ -1019,84 +1018,6 @@ public class MapMarkersHelper { return mapMarkers; } - public String saveMarkersToFile(String fileName) { - GPXFile gpxFile = generateGpx(); - String dirName = IndexConstants.GPX_INDEX_DIR + IndexConstants.MAP_MARKERS_INDEX_DIR; - File dir = ctx.getAppPath(dirName); - if (!dir.exists()) { - dir.mkdirs(); - } - String uniqueFileName = FileUtils.createUniqueFileName(ctx, fileName, dirName, IndexConstants.GPX_FILE_EXT); - File fout = new File(dir, uniqueFileName + IndexConstants.GPX_FILE_EXT); - GPXUtilities.writeGpxFile(fout, gpxFile); - - return fout.getAbsolutePath(); - } - - public GPXFile generateGpx() { - return generateGpx(mapMarkers, false); - } - - public GPXFile generateGpx(List markers, boolean completeBackup) { - SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT, Locale.US); - format.setTimeZone(TimeZone.getTimeZone("UTC")); - - GPXFile gpxFile = new GPXFile(Version.getFullVersion(ctx)); - for (MapMarker marker : markers) { - WptPt wpt = new WptPt(); - wpt.lat = marker.getLatitude(); - wpt.lon = marker.getLongitude(); - wpt.name = marker.getOnlyName(); - wpt.setColor(ContextCompat.getColor(ctx, MapMarker.getColorId(marker.colorIndex))); - if (completeBackup) { - if (marker.creationDate != 0) { - wpt.getExtensionsToWrite().put(CREATION_DATE, format.format(new Date(marker.creationDate))); - } - if (marker.visitedDate != 0) { - wpt.getExtensionsToWrite().put(VISITED_DATE, format.format(new Date(marker.visitedDate))); - } - } - gpxFile.addPoint(wpt); - } - return gpxFile; - } - - public List readMarkersFromGpx(GPXFile gpxFile, boolean history) { - SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT, Locale.US); - format.setTimeZone(TimeZone.getTimeZone("UTC")); - - List mapMarkers = new ArrayList<>(); - for (WptPt point : gpxFile.getPoints()) { - LatLon latLon = new LatLon(point.lat, point.lon); - int colorIndex = MapMarker.getColorIndex(ctx, point.getColor()); - PointDescription name = new PointDescription(PointDescription.POINT_TYPE_LOCATION, point.name); - - MapMarker marker = new MapMarker(latLon, name, colorIndex, false, 0); - - String visitedDateStr = point.getExtensionsToRead().get(VISITED_DATE); - String creationDateStr = point.getExtensionsToRead().get(CREATION_DATE); - marker.visitedDate = parseTime(visitedDateStr, format); - marker.creationDate = parseTime(creationDateStr, format); - marker.history = history; - marker.nextKey = history ? MapMarkersDbHelper.HISTORY_NEXT_VALUE : MapMarkersDbHelper.TAIL_NEXT_VALUE; - - mapMarkers.add(marker); - } - return mapMarkers; - } - - private static long parseTime(String text, SimpleDateFormat format) { - long time = 0; - if (text != null) { - try { - time = format.parse(text).getTime(); - } catch (ParseException e) { - LOG.error(e); - } - } - return time; - } - // --------------------------------------------------------------------------------------------- // accessors to active markers: @@ -1161,16 +1082,16 @@ public class MapMarkersHelper { // accessors to markers groups: - private void addToGroupsList(MapMarkersGroup group) { - List copyList = new ArrayList<>(mapMarkersGroups); + private void addToGroupsList(ItineraryGroup group) { + List copyList = new ArrayList<>(itineraryGroups); copyList.add(group); - mapMarkersGroups = copyList; + itineraryGroups = copyList; } - private void removeFromGroupsList(MapMarkersGroup group) { - List copyList = new ArrayList<>(mapMarkersGroups); + private void removeFromGroupsList(ItineraryGroup group) { + List copyList = new ArrayList<>(itineraryGroups); copyList.remove(group); - mapMarkersGroups = copyList; + itineraryGroups = copyList; } // --------------------------------------------------------------------------------------------- @@ -1192,16 +1113,16 @@ public class MapMarkersHelper { private class SyncGroupTask extends AsyncTask { - private MapMarkersGroup group; + private ItineraryGroup group; - SyncGroupTask(MapMarkersGroup group) { + SyncGroupTask(ItineraryGroup group) { this.group = group; } @Override protected void onPreExecute() { if (!syncListeners.isEmpty()) { - ctx.runInUIThread(new Runnable() { + app.runInUIThread(new Runnable() { @Override public void run() { for (OnGroupSyncedListener listener : syncListeners) { @@ -1267,7 +1188,7 @@ public class MapMarkersHelper { @Override protected void onPostExecute(Void aVoid) { if (!syncListeners.isEmpty()) { - ctx.runInUIThread(new Runnable() { + app.runInUIThread(new Runnable() { @Override public void run() { for (OnGroupSyncedListener listener : syncListeners) { diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/ItinerarySaveHelper.java b/OsmAnd/src/net/osmand/plus/mapmarkers/ItinerarySaveHelper.java new file mode 100644 index 0000000000..992acc70f7 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/ItinerarySaveHelper.java @@ -0,0 +1,265 @@ +package net.osmand.plus.mapmarkers; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + +import net.osmand.FileUtils; +import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.GPXExtensionsWriter; +import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.WptPt; +import net.osmand.IndexConstants; +import net.osmand.PlatformUtil; +import net.osmand.data.LatLon; +import net.osmand.data.PointDescription; +import net.osmand.plus.FavouritesDbHelper; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.Version; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; +import org.xmlpull.v1.XmlSerializer; + +import java.io.File; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.TimeZone; + +import static net.osmand.GPXUtilities.writeNotNullText; +import static net.osmand.plus.FavouritesDbHelper.backup; + +public class ItinerarySaveHelper { + + private static final Log log = PlatformUtil.getLog(ItinerarySaveHelper.class); + + private static final String VISITED_DATE = "visited_date"; + private static final String CREATION_DATE = "creation_date"; + + private static final String CATEGORIES_SPLIT = ","; + private static final String FILE_TO_SAVE = "itinerary.gpx"; + private static final String FILE_TO_BACKUP = "itinerary_bak.gpx"; + private static final String ITINERARY_ID = "itinerary_id"; + private static final String ITINERARY_GROUP = "itinerary_group"; + private static final String GPX_ORIGIN = "gpx_origin"; + private static final String FAVOURITES_ORIGIN = "favourites_origin"; + + private static final SimpleDateFormat GPX_TIME_FORMAT = new SimpleDateFormat(GPXUtilities.GPX_TIME_FORMAT, Locale.US); + + static { + GPX_TIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + private OsmandApplication app; + private ItineraryHelper itineraryHelper; + + public ItinerarySaveHelper(OsmandApplication app, ItineraryHelper itineraryHelper) { + this.app = app; + this.itineraryHelper = itineraryHelper; + } + + private File getInternalFile() { + return app.getFileStreamPath(FILE_TO_BACKUP); + } + + public File getExternalFile() { + return new File(app.getAppPath(null), FILE_TO_SAVE); + } + + public File getBackupFile() { + return FavouritesDbHelper.getBackupFile(app, "itinerary_bak_"); + } + + public void saveGroups() { + try { + saveFile(getInternalFile()); + saveFile(getExternalFile()); + backup(getBackupFile(), getExternalFile()); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + + public Exception saveFile(File file) { + List groups = itineraryHelper.getItineraryGroups(); + GPXFile gpxFile = generateGpx(groups); + return GPXUtilities.writeGpxFile(file, gpxFile); + } + + private void assignRouteExtensionWriter(GPXFile gpxFile, final List groups) { + if (gpxFile.getExtensionsWriter() == null) { + gpxFile.setExtensionsWriter(new GPXExtensionsWriter() { + @Override + public void writeExtensions(XmlSerializer serializer) { + for (ItineraryGroupInfo group : groups) { + try { + serializer.startTag(null, "osmand:" + ITINERARY_GROUP); + + writeNotNullText(serializer, "osmand:name", group.name); + writeNotNullText(serializer, "osmand:type", group.type); + writeNotNullText(serializer, "osmand:path", group.path); + writeNotNullText(serializer, "osmand:alias", group.alias); + writeNotNullText(serializer, "osmand:categories", group.categories); + + serializer.endTag(null, "osmand:" + ITINERARY_GROUP); + } catch (IOException e) { + log.error(e); + } + } + } + }); + } + } + + public String saveMarkersToFile(String fileName) { + GPXFile gpxFile = generateGpx(); + String dirName = IndexConstants.GPX_INDEX_DIR + IndexConstants.MAP_MARKERS_INDEX_DIR; + File dir = app.getAppPath(dirName); + if (!dir.exists()) { + dir.mkdirs(); + } + String uniqueFileName = FileUtils.createUniqueFileName(app, fileName, dirName, IndexConstants.GPX_FILE_EXT); + File fout = new File(dir, uniqueFileName + IndexConstants.GPX_FILE_EXT); + GPXUtilities.writeGpxFile(fout, gpxFile); + + return fout.getAbsolutePath(); + } + + public GPXFile generateGpx() { + return generateGpx(itineraryHelper.getMapMarkers(), false); + } + + public GPXFile generateGpx(List markers, boolean completeBackup) { + GPXFile gpxFile = new GPXFile(Version.getFullVersion(app)); + for (MapMarker marker : markers) { + WptPt wpt = toWpt(marker); + wpt.setColor(ContextCompat.getColor(app, MapMarker.getColorId(marker.colorIndex))); + if (completeBackup) { + if (marker.creationDate != 0) { + wpt.getExtensionsToWrite().put(CREATION_DATE, GPX_TIME_FORMAT.format(new Date(marker.creationDate))); + } + if (marker.visitedDate != 0) { + wpt.getExtensionsToWrite().put(VISITED_DATE, GPX_TIME_FORMAT.format(new Date(marker.visitedDate))); + } + } + gpxFile.addPoint(wpt); + } + return gpxFile; + } + + public GPXFile generateGpx(List itineraryGroups) { + GPXFile gpxFile = new GPXFile(Version.getFullVersion(app)); + List groups = new ArrayList<>(); + for (ItineraryGroup group : itineraryGroups) { + ItineraryGroupInfo groupInfo = ItineraryGroupInfo.createGroupInfo(app, group); + + for (MapMarker marker : group.getMarkers()) { + WptPt wptPt = toWpt(marker); + + String markerId = marker.id; + String name = marker.getName(app); + int index = markerId.indexOf(name); + if (index != -1) { + markerId = markerId.substring(index + name.length()); + } + wptPt.getExtensionsToWrite().put(ITINERARY_ID, groupInfo.type + ":" + markerId); + + if (group.getType() == ItineraryType.TRACK) { + wptPt.getExtensionsToWrite().put(GPX_ORIGIN, groupInfo.path); + } else { + wptPt.getExtensionsToWrite().put(FAVOURITES_ORIGIN, groupInfo.name); + } + gpxFile.addPoint(wptPt); + } + groups.add(groupInfo); + } + assignRouteExtensionWriter(gpxFile, groups); + return gpxFile; + } + + public List readMarkersFromGpx(GPXFile gpxFile, boolean history) { + List mapMarkers = new ArrayList<>(); + for (WptPt point : gpxFile.getPoints()) { + MapMarker marker = fromWpt(point, app, history); + mapMarkers.add(marker); + } + return mapMarkers; + } + + public static MapMarker fromWpt(@NonNull WptPt point, @NonNull Context ctx, boolean history) { + LatLon latLon = new LatLon(point.lat, point.lon); + int colorIndex = MapMarker.getColorIndex(ctx, point.getColor()); + PointDescription name = new PointDescription(PointDescription.POINT_TYPE_LOCATION, point.name); + + MapMarker marker = new MapMarker(latLon, name, colorIndex, false, 0); + + String visitedDateStr = point.getExtensionsToRead().get(VISITED_DATE); + String creationDateStr = point.getExtensionsToRead().get(CREATION_DATE); + marker.visitedDate = parseTime(visitedDateStr); + marker.creationDate = parseTime(creationDateStr); + marker.history = history; + marker.nextKey = history ? MapMarkersDbHelper.HISTORY_NEXT_VALUE : MapMarkersDbHelper.TAIL_NEXT_VALUE; + + return marker; + } + + public static WptPt toWpt(@NonNull MapMarker marker) { + WptPt wpt = new WptPt(); + wpt.lat = marker.getLatitude(); + wpt.lon = marker.getLongitude(); + wpt.name = marker.getOnlyName(); + return wpt; + } + + private static long parseTime(String text) { + long time = 0; + if (text != null) { + try { + time = GPX_TIME_FORMAT.parse(text).getTime(); + } catch (ParseException e) { + log.error(e); + } + } + return time; + } + + public static class ItineraryGroupInfo { + + public String name; + public String type; + public String path; + public String alias; + public String categories; + + public static ItineraryGroupInfo createGroupInfo(OsmandApplication app, ItineraryGroup group) { + ItineraryGroupInfo groupInfo = new ItineraryGroupInfo(); + groupInfo.type = group.getType().getTypeName(); + groupInfo.name = !Algorithms.isEmpty(group.getName()) ? group.getName() : null; + + Set wptCategories = group.getWptCategories(); + if (!Algorithms.isEmpty(wptCategories)) { + groupInfo.categories = Algorithms.encodeStringSet(wptCategories, CATEGORIES_SPLIT); + } + if (group.getType() == ItineraryType.TRACK) { + String path = group.getId(); + String gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR).getAbsolutePath(); + int index = path.indexOf(gpxDir); + if (index != -1) { + path = path.substring(gpxDir.length() + 1); + } + groupInfo.path = path; + groupInfo.alias = groupInfo.type + ":" + path; + } else { + groupInfo.alias = groupInfo.type + (Algorithms.isEmpty(groupInfo.name) ? "" : ":" + groupInfo.name); + } + return groupInfo; + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDbHelper.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDbHelper.java index d3f7219422..3f2abb46df 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDbHelper.java @@ -16,9 +16,10 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; +import static net.osmand.util.MapUtils.createShortLinkString; + public class MapMarkersDbHelper { private static final int DB_VERSION = 13; @@ -303,7 +304,7 @@ public class MapMarkersDbHelper { private void insertLast(SQLiteConnection db, MapMarker marker) { long currentTime = System.currentTimeMillis(); if (marker.id == null) { - marker.id = String.valueOf(currentTime) + String.valueOf(new Random().nextInt(900) + 100); + marker.id = marker.getName(context) + createShortLinkString(marker.point.getLatitude(), marker.point.getLongitude(), 15); } marker.creationDate = currentTime; String descr = PointDescription.serializeToString(marker.getOriginalPointDescription());