aboutsummaryrefslogtreecommitdiffstats
path: root/src/cgeo/geocaching/files/GPXParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgeo/geocaching/files/GPXParser.java')
-rw-r--r--src/cgeo/geocaching/files/GPXParser.java1484
1 files changed, 742 insertions, 742 deletions
diff --git a/src/cgeo/geocaching/files/GPXParser.java b/src/cgeo/geocaching/files/GPXParser.java
index a9978c5..1e1458a 100644
--- a/src/cgeo/geocaching/files/GPXParser.java
+++ b/src/cgeo/geocaching/files/GPXParser.java
@@ -1,17 +1,15 @@
package cgeo.geocaching.files;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgBase;
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.cgLog;
+import cgeo.geocaching.cgSearch;
+import cgeo.geocaching.cgSettings;
+import cgeo.geocaching.cgTrackable;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.geopoint.Geopoint;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.Attributes;
@@ -25,435 +23,437 @@ import android.sax.RootElement;
import android.sax.StartElementListener;
import android.util.Log;
import android.util.Xml;
-import cgeo.geocaching.R;
-import cgeo.geocaching.cgBase;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgLog;
-import cgeo.geocaching.cgSearch;
-import cgeo.geocaching.cgSettings;
-import cgeo.geocaching.cgTrackable;
-import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.connector.ConnectorFactory;
-import cgeo.geocaching.geopoint.Geopoint;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public abstract class GPXParser extends FileParser {
- private static final SimpleDateFormat formatSimple = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // 2010-04-20T07:00:00Z
- private static final SimpleDateFormat formatTimezone = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.000'Z"); // 2010-04-20T01:01:03.000-04:00
-
- private static final Pattern patternGeocode = Pattern.compile("([A-Z]{2}[0-9A-Z]+)", Pattern.CASE_INSENSITIVE);
- private static final Pattern patternGuid = Pattern.compile(".*" + Pattern.quote("guid=") + "([0-9a-z\\-]+)", Pattern.CASE_INSENSITIVE);
- private static final String[] nsGCList = new String[] {
- "http://www.groundspeak.com/cache/1/1", // PQ 1.1
- "http://www.groundspeak.com/cache/1/0/1", // PQ 1.0.1
- "http://www.groundspeak.com/cache/1/0", // PQ 1.0
- };
-
- private static final String GSAK_NS = "http://www.gsak.net/xmlv1/5";
-
- private static cgeoapplication app = null;
- private int listId = 1;
- private cgSearch search = null;
- final protected String namespace;
- final private String version;
- private Handler handler = null;
-
- private cgCache cache = new cgCache();
- private cgTrackable trackable = new cgTrackable();
- private cgLog log = new cgLog();
-
- private String type = null;
- private String sym = null;
- private String name = null;
- private String cmt = null;
- private String desc = null;
- protected String[] userData = new String[5]; // take 5 cells, that makes indexing 1..4 easier
-
- private final class UserDataListener implements EndTextElementListener {
- private int index;
-
- public UserDataListener(int index) {
- this.index = index;
- }
-
- @Override
- public void end(String user) {
- userData[index] = validate(user);
- }
- }
-
- private static final class CacheAttributeTranslator {
- // List of cache attributes matching IDs used in GPX files.
- // The ID is represented by the position of the String in the array.
- // Strings are not used as text but as resource IDs of strings, just to be aware of changes
- // made in strings.xml which then will lead to compile errors here and not to runtime errors.
- private static final int[] CACHE_ATTRIBUTES = {
- -1, // 0
- R.string.attribute_dogs_yes, // 1
- R.string.attribute_fee_yes, // 2
- R.string.attribute_rappelling_yes, // 3
- R.string.attribute_boat_yes, // 4
- R.string.attribute_scuba_yes, // 5
- R.string.attribute_kids_yes, // 6
- R.string.attribute_onehour_yes, // 7
- R.string.attribute_scenic_yes, // 8
- R.string.attribute_hiking_yes, // 9
- R.string.attribute_climbing_yes, // 10
- R.string.attribute_wading_yes, // 11
- R.string.attribute_swimming_yes, // 12
- R.string.attribute_available_yes, // 13
- R.string.attribute_night_yes, // 14
- R.string.attribute_winter_yes, // 15
- -1, // 16
- R.string.attribute_poisonoak_yes, // 17
- R.string.attribute_dangerousanimals_yes, // 18
- R.string.attribute_ticks_yes, // 19
- R.string.attribute_mine_yes, // 20
- R.string.attribute_cliff_yes, // 21
- R.string.attribute_hunting_yes, // 22
- R.string.attribute_danger_yes, // 23
- R.string.attribute_wheelchair_yes, // 24
- R.string.attribute_parking_yes, // 25
- R.string.attribute_public_yes, // 26
- R.string.attribute_water_yes, // 27
- R.string.attribute_restrooms_yes, // 28
- R.string.attribute_phone_yes, // 29
- R.string.attribute_picnic_yes, // 30
- R.string.attribute_camping_yes, // 31
- R.string.attribute_bicycles_yes, // 32
- R.string.attribute_motorcycles_yes, // 33
- R.string.attribute_quads_yes, // 34
- R.string.attribute_jeeps_yes, // 35
- R.string.attribute_snowmobiles_yes, // 36
- R.string.attribute_horses_yes, // 37
- R.string.attribute_campfires_yes, // 38
- R.string.attribute_thorn_yes, // 39
- R.string.attribute_stealth_yes, // 40
- R.string.attribute_stroller_yes, // 41
- R.string.attribute_firstaid_yes, // 42
- R.string.attribute_cow_yes, // 43
- R.string.attribute_flashlight_yes, // 44
- R.string.attribute_landf_yes, // 45
- R.string.attribute_rv_yes, // 46
- R.string.attribute_field_puzzle_yes, // 47
- R.string.attribute_uv_yes, // 48
- R.string.attribute_snowshoes_yes, // 49
- R.string.attribute_skiis_yes, // 50
- R.string.attribute_s_tool_yes, // 51
- R.string.attribute_nightcache_yes, // 52
- R.string.attribute_parkngrab_yes, // 53
- R.string.attribute_abandonedbuilding_yes, // 54
- R.string.attribute_hike_short_yes, // 55
- R.string.attribute_hike_med_yes, // 56
- R.string.attribute_hike_long_yes, // 57
- R.string.attribute_fuel_yes, // 58
- R.string.attribute_food_yes, // 59
- R.string.attribute_wirelessbeacon_yes, // 60
- R.string.attribute_partnership_yes, // 61
- R.string.attribute_seasonal_yes, // 62
- R.string.attribute_touristok_yes, // 63
- R.string.attribute_treeclimbing_yes, // 64
- R.string.attribute_frontyard_yes, // 65
- R.string.attribute_teamwork_yes, // 66
- };
+ private static final SimpleDateFormat formatSimple = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // 2010-04-20T07:00:00Z
+ private static final SimpleDateFormat formatTimezone = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.000'Z"); // 2010-04-20T01:01:03.000-04:00
+
+ private static final Pattern patternGeocode = Pattern.compile("([A-Z]{2}[0-9A-Z]+)", Pattern.CASE_INSENSITIVE);
+ private static final Pattern patternGuid = Pattern.compile(".*" + Pattern.quote("guid=") + "([0-9a-z\\-]+)", Pattern.CASE_INSENSITIVE);
+ private static final String[] nsGCList = new String[] {
+ "http://www.groundspeak.com/cache/1/1", // PQ 1.1
+ "http://www.groundspeak.com/cache/1/0/1", // PQ 1.0.1
+ "http://www.groundspeak.com/cache/1/0", // PQ 1.0
+ };
+
+ private static final String GSAK_NS = "http://www.gsak.net/xmlv1/5";
+
+ private static cgeoapplication app = null;
+ private int listId = 1;
+ private cgSearch search = null;
+ final protected String namespace;
+ final private String version;
+ private Handler handler = null;
+
+ private cgCache cache = new cgCache();
+ private cgTrackable trackable = new cgTrackable();
+ private cgLog log = new cgLog();
+
+ private String type = null;
+ private String sym = null;
+ private String name = null;
+ private String cmt = null;
+ private String desc = null;
+ protected String[] userData = new String[5]; // take 5 cells, that makes indexing 1..4 easier
+
+ private final class UserDataListener implements EndTextElementListener {
+ private int index;
+
+ public UserDataListener(int index) {
+ this.index = index;
+ }
+
+ @Override
+ public void end(String user) {
+ userData[index] = validate(user);
+ }
+ }
+
+ private static final class CacheAttributeTranslator {
+ // List of cache attributes matching IDs used in GPX files.
+ // The ID is represented by the position of the String in the array.
+ // Strings are not used as text but as resource IDs of strings, just to be aware of changes
+ // made in strings.xml which then will lead to compile errors here and not to runtime errors.
+ private static final int[] CACHE_ATTRIBUTES = {
+ -1, // 0
+ R.string.attribute_dogs_yes, // 1
+ R.string.attribute_fee_yes, // 2
+ R.string.attribute_rappelling_yes, // 3
+ R.string.attribute_boat_yes, // 4
+ R.string.attribute_scuba_yes, // 5
+ R.string.attribute_kids_yes, // 6
+ R.string.attribute_onehour_yes, // 7
+ R.string.attribute_scenic_yes, // 8
+ R.string.attribute_hiking_yes, // 9
+ R.string.attribute_climbing_yes, // 10
+ R.string.attribute_wading_yes, // 11
+ R.string.attribute_swimming_yes, // 12
+ R.string.attribute_available_yes, // 13
+ R.string.attribute_night_yes, // 14
+ R.string.attribute_winter_yes, // 15
+ -1, // 16
+ R.string.attribute_poisonoak_yes, // 17
+ R.string.attribute_dangerousanimals_yes, // 18
+ R.string.attribute_ticks_yes, // 19
+ R.string.attribute_mine_yes, // 20
+ R.string.attribute_cliff_yes, // 21
+ R.string.attribute_hunting_yes, // 22
+ R.string.attribute_danger_yes, // 23
+ R.string.attribute_wheelchair_yes, // 24
+ R.string.attribute_parking_yes, // 25
+ R.string.attribute_public_yes, // 26
+ R.string.attribute_water_yes, // 27
+ R.string.attribute_restrooms_yes, // 28
+ R.string.attribute_phone_yes, // 29
+ R.string.attribute_picnic_yes, // 30
+ R.string.attribute_camping_yes, // 31
+ R.string.attribute_bicycles_yes, // 32
+ R.string.attribute_motorcycles_yes, // 33
+ R.string.attribute_quads_yes, // 34
+ R.string.attribute_jeeps_yes, // 35
+ R.string.attribute_snowmobiles_yes, // 36
+ R.string.attribute_horses_yes, // 37
+ R.string.attribute_campfires_yes, // 38
+ R.string.attribute_thorn_yes, // 39
+ R.string.attribute_stealth_yes, // 40
+ R.string.attribute_stroller_yes, // 41
+ R.string.attribute_firstaid_yes, // 42
+ R.string.attribute_cow_yes, // 43
+ R.string.attribute_flashlight_yes, // 44
+ R.string.attribute_landf_yes, // 45
+ R.string.attribute_rv_yes, // 46
+ R.string.attribute_field_puzzle_yes, // 47
+ R.string.attribute_uv_yes, // 48
+ R.string.attribute_snowshoes_yes, // 49
+ R.string.attribute_skiis_yes, // 50
+ R.string.attribute_s_tool_yes, // 51
+ R.string.attribute_nightcache_yes, // 52
+ R.string.attribute_parkngrab_yes, // 53
+ R.string.attribute_abandonedbuilding_yes, // 54
+ R.string.attribute_hike_short_yes, // 55
+ R.string.attribute_hike_med_yes, // 56
+ R.string.attribute_hike_long_yes, // 57
+ R.string.attribute_fuel_yes, // 58
+ R.string.attribute_food_yes, // 59
+ R.string.attribute_wirelessbeacon_yes, // 60
+ R.string.attribute_partnership_yes, // 61
+ R.string.attribute_seasonal_yes, // 62
+ R.string.attribute_touristok_yes, // 63
+ R.string.attribute_treeclimbing_yes, // 64
+ R.string.attribute_frontyard_yes, // 65
+ R.string.attribute_teamwork_yes, // 66
+ };
private static final String YES = "_yes";
private static final String NO = "_no";
private static final Pattern BASENAME_PATTERN = Pattern.compile("^.*attribute_(.*)(_yes|_no)");
- // map GPX-Attribute-Id to baseName
- public static String getBaseName(final int id) {
- // get String out of array
- if (CACHE_ATTRIBUTES.length <= id) {
- return null;
- }
- final int stringId = CACHE_ATTRIBUTES[id];
- if (stringId == -1) {
- return null; // id not found
- }
- // get text for string
- String stringName = null;
- try {
- stringName = app.getResources().getResourceName(stringId);
- } catch (NullPointerException e) {
- return null;
- }
- if (stringName == null) {
- return null;
- }
- // cut out baseName
- final Matcher m = BASENAME_PATTERN.matcher(stringName);
- if (! m.matches()) {
- return null;
- }
- return m.group(1);
- }
-
- // @return baseName + "_yes" or "_no" e.g. "food_no" or "uv_yes"
- public static String getInternalId(final int attributeId, final boolean active) {
- final String baseName = CacheAttributeTranslator.getBaseName(attributeId);
- if (baseName == null) {
- return null;
- }
- return baseName + (active ? YES : NO);
- }
- }
-
- protected GPXParser(cgeoapplication appIn, int listIdIn, cgSearch searchIn, String namespaceIn, String versionIn) {
- app = appIn;
- listId = listIdIn;
- search = searchIn;
- namespace = namespaceIn;
- version = versionIn;
- }
-
- private static Date parseDate(String inputUntrimmed) throws ParseException {
- final String input = inputUntrimmed.trim();
- if (input.length() >= 3 && input.charAt(input.length() - 3) == ':') {
- final String removeColon = input.substring(0, input.length() - 3) + input.substring(input.length() - 2);
- return formatTimezone.parse(removeColon);
- }
- return formatSimple.parse(input);
- }
-
- public UUID parse(final InputStream stream, Handler handlerIn) {
- handler = handlerIn;
-
- final RootElement root = new RootElement(namespace, "gpx");
- final Element waypoint = root.getChild(namespace, "wpt");
-
- // waypoint - attributes
- waypoint.setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attrs) {
- try {
- if (attrs.getIndex("lat") > -1 && attrs.getIndex("lon") > -1) {
- cache.coords = new Geopoint(new Double(attrs.getValue("lat")),
- new Double(attrs.getValue("lon")));
- }
- } catch (Exception e) {
- Log.w(cgSettings.tag, "Failed to parse waypoint's latitude and/or longitude.");
- }
- }
- });
-
- // waypoint
- waypoint.setEndElementListener(new EndElementListener() {
-
- @Override
- public void end() {
- if (StringUtils.isBlank(cache.geocode)) {
- // try to find geocode somewhere else
- findGeoCode(name);
- findGeoCode(desc);
- findGeoCode(cmt);
- }
-
- if (StringUtils.isNotBlank(cache.geocode)
- && cache.coords != null
- && ((type == null && sym == null)
- || (type != null && type.indexOf("geocache") > -1)
- || (sym != null && sym.indexOf("geocache") > -1))) {
- fixCache(cache);
- cache.reason = listId;
- cache.detailed = true;
-
- if (StringUtils.isBlank(cache.personalNote)) {
- StringBuilder buffer = new StringBuilder();
- for (int i = 0; i < userData.length; i++) {
- if (StringUtils.isNotBlank(userData[i])) {
- buffer.append(' ').append(userData[i]);
- }
- }
- String note = buffer.toString().trim();
- if (StringUtils.isNotBlank(note)) {
- cache.personalNote = note;
- }
- }
-
- app.addCacheToSearch(search, cache);
- }
-
- showFinishedMessage(handler, search);
-
- resetCache();
- }
- });
-
- // waypoint.time
- waypoint.getChild(namespace, "time").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- try {
- cache.hidden = parseDate(body);
- } catch (Exception e) {
- Log.w(cgSettings.tag, "Failed to parse cache date: " + e.toString());
- }
- }
- });
-
- // waypoint.name
- waypoint.getChild(namespace, "name").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- name = body;
-
- final String content = body.trim();
- cache.name = content;
-
- findGeoCode(cache.name);
- findGeoCode(cache.description);
- }
- });
-
- // waypoint.desc
- waypoint.getChild(namespace, "desc").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- desc = body;
-
- cache.shortdesc = validate(body);
- }
- });
-
- // waypoint.cmt
- waypoint.getChild(namespace, "cmt").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- cmt = body;
-
- cache.description = validate(body);
- }
- });
-
- // waypoint.type
- waypoint.getChild(namespace, "type").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- final String[] content = body.split("\\|");
- if (content.length > 0) {
- type = content[0].toLowerCase().trim();
- }
- }
- });
-
- // waypoint.sym
- waypoint.getChild(namespace, "sym").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- body = body.toLowerCase();
- sym = body;
- if (body.indexOf("geocache") != -1 && body.indexOf("found") != -1) {
- cache.found = true;
- }
- }
- });
-
- // waypoint.url
- waypoint.getChild(namespace, "url").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String url) {
- final Matcher matcher = patternGuid.matcher(url);
- if (matcher.matches()) {
- String guid = matcher.group(1);
- if (StringUtils.isNotBlank(guid)) {
- cache.guid = guid;
- }
- }
- }
- });
-
- // for GPX 1.0, cache info comes from waypoint node (so called private children,
- // for GPX 1.1 from extensions node
- final Element cacheParent = getCacheParent(waypoint);
-
-
- // GSAK extensions
- final Element gsak = cacheParent.getChild(GSAK_NS, "wptExtension");
- gsak.getChild(GSAK_NS, "Watch").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String watchList) {
- cache.onWatchlist = Boolean.valueOf(watchList.trim());
- }
- });
-
- gsak.getChild(GSAK_NS, "UserData").setEndTextElementListener(new UserDataListener(1));
-
- for (int i = 2; i <= 4; i++) {
- gsak.getChild(GSAK_NS, "User" + i).setEndTextElementListener(new UserDataListener(i));
- }
-
- // 3 different versions of the GC schema
- for (String nsGC : nsGCList) {
- // waypoints.cache
- final Element gcCache = cacheParent.getChild(nsGC, "cache");
-
- gcCache.setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attrs) {
- try {
- if (attrs.getIndex("id") > -1) {
- cache.cacheId = attrs.getValue("id");
- }
- if (attrs.getIndex("archived") > -1) {
- cache.archived = attrs.getValue("archived").equalsIgnoreCase("true");
- }
- if (attrs.getIndex("available") > -1) {
- cache.disabled = !attrs.getValue("available").equalsIgnoreCase("true");
- }
- } catch (Exception e) {
- Log.w(cgSettings.tag, "Failed to parse cache attributes.");
- }
- }
- });
-
- // waypoint.cache.name
- gcCache.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String cacheName) {
- cache.name = validate(cacheName);
- }
- });
-
- // waypoint.cache.owner
- gcCache.getChild(nsGC, "owner").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String cacheOwner) {
- cache.owner = validate(cacheOwner);
- }
- });
-
- // waypoint.cache.type
- gcCache.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- setType(validate(body.toLowerCase()));
- }
- });
-
- // waypoint.cache.container
- gcCache.getChild(nsGC, "container").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- cache.size = validate(body.toLowerCase());
- }
- });
-
- // waypoint.cache.attributes
- // @see issue #299
+ // map GPX-Attribute-Id to baseName
+ public static String getBaseName(final int id) {
+ // get String out of array
+ if (CACHE_ATTRIBUTES.length <= id) {
+ return null;
+ }
+ final int stringId = CACHE_ATTRIBUTES[id];
+ if (stringId == -1) {
+ return null; // id not found
+ }
+ // get text for string
+ String stringName = null;
+ try {
+ stringName = app.getResources().getResourceName(stringId);
+ } catch (NullPointerException e) {
+ return null;
+ }
+ if (stringName == null) {
+ return null;
+ }
+ // cut out baseName
+ final Matcher m = BASENAME_PATTERN.matcher(stringName);
+ if (!m.matches()) {
+ return null;
+ }
+ return m.group(1);
+ }
+
+ // @return baseName + "_yes" or "_no" e.g. "food_no" or "uv_yes"
+ public static String getInternalId(final int attributeId, final boolean active) {
+ final String baseName = CacheAttributeTranslator.getBaseName(attributeId);
+ if (baseName == null) {
+ return null;
+ }
+ return baseName + (active ? YES : NO);
+ }
+ }
+
+ protected GPXParser(cgeoapplication appIn, int listIdIn, cgSearch searchIn, String namespaceIn, String versionIn) {
+ app = appIn;
+ listId = listIdIn;
+ search = searchIn;
+ namespace = namespaceIn;
+ version = versionIn;
+ }
+
+ private static Date parseDate(String inputUntrimmed) throws ParseException {
+ final String input = inputUntrimmed.trim();
+ if (input.length() >= 3 && input.charAt(input.length() - 3) == ':') {
+ final String removeColon = input.substring(0, input.length() - 3) + input.substring(input.length() - 2);
+ return formatTimezone.parse(removeColon);
+ }
+ return formatSimple.parse(input);
+ }
+
+ public UUID parse(final InputStream stream, Handler handlerIn) {
+ handler = handlerIn;
+
+ final RootElement root = new RootElement(namespace, "gpx");
+ final Element waypoint = root.getChild(namespace, "wpt");
+
+ // waypoint - attributes
+ waypoint.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("lat") > -1 && attrs.getIndex("lon") > -1) {
+ cache.coords = new Geopoint(new Double(attrs.getValue("lat")),
+ new Double(attrs.getValue("lon")));
+ }
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse waypoint's latitude and/or longitude.");
+ }
+ }
+ });
+
+ // waypoint
+ waypoint.setEndElementListener(new EndElementListener() {
+
+ @Override
+ public void end() {
+ if (StringUtils.isBlank(cache.geocode)) {
+ // try to find geocode somewhere else
+ findGeoCode(name);
+ findGeoCode(desc);
+ findGeoCode(cmt);
+ }
+
+ if (StringUtils.isNotBlank(cache.geocode)
+ && cache.coords != null
+ && ((type == null && sym == null)
+ || (type != null && type.indexOf("geocache") > -1)
+ || (sym != null && sym.indexOf("geocache") > -1))) {
+ fixCache(cache);
+ cache.reason = listId;
+ cache.detailed = true;
+
+ if (StringUtils.isBlank(cache.personalNote)) {
+ StringBuilder buffer = new StringBuilder();
+ for (int i = 0; i < userData.length; i++) {
+ if (StringUtils.isNotBlank(userData[i])) {
+ buffer.append(' ').append(userData[i]);
+ }
+ }
+ String note = buffer.toString().trim();
+ if (StringUtils.isNotBlank(note)) {
+ cache.personalNote = note;
+ }
+ }
+
+ app.addCacheToSearch(search, cache);
+ }
+
+ showFinishedMessage(handler, search);
+
+ resetCache();
+ }
+ });
+
+ // waypoint.time
+ waypoint.getChild(namespace, "time").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ try {
+ cache.hidden = parseDate(body);
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse cache date: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.name
+ waypoint.getChild(namespace, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ name = body;
+
+ final String content = body.trim();
+ cache.name = content;
+
+ findGeoCode(cache.name);
+ findGeoCode(cache.description);
+ }
+ });
+
+ // waypoint.desc
+ waypoint.getChild(namespace, "desc").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ desc = body;
+
+ cache.shortdesc = validate(body);
+ }
+ });
+
+ // waypoint.cmt
+ waypoint.getChild(namespace, "cmt").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ cmt = body;
+
+ cache.description = validate(body);
+ }
+ });
+
+ // waypoint.type
+ waypoint.getChild(namespace, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String[] content = body.split("\\|");
+ if (content.length > 0) {
+ type = content[0].toLowerCase().trim();
+ }
+ }
+ });
+
+ // waypoint.sym
+ waypoint.getChild(namespace, "sym").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ body = body.toLowerCase();
+ sym = body;
+ if (body.indexOf("geocache") != -1 && body.indexOf("found") != -1) {
+ cache.found = true;
+ }
+ }
+ });
+
+ // waypoint.url
+ waypoint.getChild(namespace, "url").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String url) {
+ final Matcher matcher = patternGuid.matcher(url);
+ if (matcher.matches()) {
+ String guid = matcher.group(1);
+ if (StringUtils.isNotBlank(guid)) {
+ cache.guid = guid;
+ }
+ }
+ }
+ });
+
+ // for GPX 1.0, cache info comes from waypoint node (so called private children,
+ // for GPX 1.1 from extensions node
+ final Element cacheParent = getCacheParent(waypoint);
+
+ // GSAK extensions
+ final Element gsak = cacheParent.getChild(GSAK_NS, "wptExtension");
+ gsak.getChild(GSAK_NS, "Watch").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String watchList) {
+ cache.onWatchlist = Boolean.valueOf(watchList.trim());
+ }
+ });
+
+ gsak.getChild(GSAK_NS, "UserData").setEndTextElementListener(new UserDataListener(1));
+
+ for (int i = 2; i <= 4; i++) {
+ gsak.getChild(GSAK_NS, "User" + i).setEndTextElementListener(new UserDataListener(i));
+ }
+
+ // 3 different versions of the GC schema
+ for (String nsGC : nsGCList) {
+ // waypoints.cache
+ final Element gcCache = cacheParent.getChild(nsGC, "cache");
+
+ gcCache.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ try {
+ if (attrs.getIndex("id") > -1) {
+ cache.cacheId = attrs.getValue("id");
+ }
+ if (attrs.getIndex("archived") > -1) {
+ cache.archived = attrs.getValue("archived").equalsIgnoreCase("true");
+ }
+ if (attrs.getIndex("available") > -1) {
+ cache.disabled = !attrs.getValue("available").equalsIgnoreCase("true");
+ }
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse cache attributes.");
+ }
+ }
+ });
+
+ // waypoint.cache.name
+ gcCache.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String cacheName) {
+ cache.name = validate(cacheName);
+ }
+ });
+
+ // waypoint.cache.owner
+ gcCache.getChild(nsGC, "owner").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String cacheOwner) {
+ cache.owner = validate(cacheOwner);
+ }
+ });
+
+ // waypoint.cache.type
+ gcCache.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ setType(validate(body.toLowerCase()));
+ }
+ });
+
+ // waypoint.cache.container
+ gcCache.getChild(nsGC, "container").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ cache.size = validate(body.toLowerCase());
+ }
+ });
+
+ // waypoint.cache.attributes
+ // @see issue #299
// <groundspeak:attributes>
// <groundspeak:attribute id="32" inc="1">Bicycles</groundspeak:attribute>
@@ -474,10 +474,10 @@ public abstract class GPXParser extends FileParser {
boolean attributeActive = Integer.parseInt(attrs.getValue("inc")) != 0;
String internalId = CacheAttributeTranslator.getInternalId(attributeId, attributeActive);
if (internalId != null) {
- if (cache.attributes == null) {
- cache.attributes = new ArrayList<String>();
- }
- cache.attributes.add(internalId);
+ if (cache.attributes == null) {
+ cache.attributes = new ArrayList<String>();
+ }
+ cache.attributes.add(internalId);
}
}
} catch (NumberFormatException e) {
@@ -487,308 +487,308 @@ public abstract class GPXParser extends FileParser {
});
// waypoint.cache.difficulty
- gcCache.getChild(nsGC, "difficulty").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- try {
- cache.difficulty = new Float(body);
- } catch (Exception e) {
- Log.w(cgSettings.tag, "Failed to parse difficulty: " + e.toString());
- }
- }
- });
-
- // waypoint.cache.terrain
- gcCache.getChild(nsGC, "terrain").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- try {
- cache.terrain = new Float(body);
- } catch (Exception e) {
- Log.w(cgSettings.tag, "Failed to parse terrain: " + e.toString());
- }
- }
- });
-
- // waypoint.cache.country
- gcCache.getChild(nsGC, "country").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String country) {
- if (StringUtils.isBlank(cache.location)) {
- cache.location = validate(country);
- } else {
- cache.location = cache.location + ", " + country.trim();
- }
- }
- });
-
- // waypoint.cache.state
- gcCache.getChild(nsGC, "state").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String state) {
- if (StringUtils.isBlank(cache.location)) {
- cache.location = validate(state);
- } else {
- cache.location = state.trim() + ", " + cache.location;
- }
- }
- });
-
- // waypoint.cache.encoded_hints
- gcCache.getChild(nsGC, "encoded_hints").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String encoded) {
- cache.hint = validate(encoded);
- }
- });
-
- gcCache.getChild(nsGC, "short_description").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String shortDesc) {
- cache.shortdesc = validate(shortDesc);
- }
- });
-
- gcCache.getChild(nsGC, "long_description").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String desc) {
- cache.description = validate(desc);
- }
- });
-
- // waypoint.cache.travelbugs
- final Element gcTBs = gcCache.getChild(nsGC, "travelbugs");
-
- // waypoint.cache.travelbugs.travelbug
- gcTBs.getChild(nsGC, "travelbug").setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attrs) {
- trackable = new cgTrackable();
-
- try {
- if (attrs.getIndex("ref") > -1) {
- trackable.geocode = attrs.getValue("ref").toUpperCase();
- }
- } catch (Exception e) {
- // nothing
- }
- }
- });
-
- // waypoint.cache.travelbug
- final Element gcTB = gcTBs.getChild(nsGC, "travelbug");
-
- gcTB.setEndElementListener(new EndElementListener() {
-
- @Override
- public void end() {
- if (StringUtils.isNotBlank(trackable.geocode) && StringUtils.isNotBlank(trackable.name)) {
- if (cache.inventory == null) {
- cache.inventory = new ArrayList<cgTrackable>();
- }
- cache.inventory.add(trackable);
- }
- }
- });
-
- // waypoint.cache.travelbugs.travelbug.name
- gcTB.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String tbName) {
- trackable.name = validate(tbName);
- }
- });
-
- // waypoint.cache.logs
- final Element gcLogs = gcCache.getChild(nsGC, "logs");
-
- // waypoint.cache.log
- final Element gcLog = gcLogs.getChild(nsGC, "log");
-
- gcLog.setStartElementListener(new StartElementListener() {
-
- @Override
- public void start(Attributes attrs) {
- log = new cgLog();
-
- try {
- if (attrs.getIndex("id") > -1) {
- log.id = Integer.parseInt(attrs.getValue("id"));
- }
- } catch (Exception e) {
- // nothing
- }
- }
- });
-
- gcLog.setEndElementListener(new EndElementListener() {
-
- @Override
- public void end() {
- if (StringUtils.isNotBlank(log.log)) {
- if (cache.logs == null) {
- cache.logs = new ArrayList<cgLog>();
- }
- cache.logs.add(log);
- }
- }
- });
-
- // waypoint.cache.logs.log.date
- gcLog.getChild(nsGC, "date").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- try {
- log.date = parseDate(body).getTime();
- } catch (Exception e) {
- Log.w(cgSettings.tag, "Failed to parse log date: " + e.toString());
- }
- }
- });
-
- // waypoint.cache.logs.log.type
- gcLog.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String body) {
- final String logType = validate(body).toLowerCase();
- if (cgBase.logTypes0.containsKey(logType)) {
- log.type = cgBase.logTypes0.get(logType);
- } else {
- log.type = cgBase.LOG_NOTE;
- }
- }
- });
-
- // waypoint.cache.logs.log.finder
- gcLog.getChild(nsGC, "finder").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String finderName) {
- log.author = validate(finderName);
- }
- });
-
- // waypoint.cache.logs.log.text
- gcLog.getChild(nsGC, "text").setEndTextElementListener(new EndTextElementListener() {
-
- @Override
- public void end(String logText) {
- log.log = validate(logText);
- }
- });
- }
- boolean parsed = false;
- try {
- Xml.parse(stream, Xml.Encoding.UTF_8, root.getContentHandler());
- parsed = true;
- } catch (IOException e) {
- Log.e(cgSettings.tag, "Cannot parse .gpx file as GPX " + version + ": could not read file!");
- } catch (SAXException e) {
- Log.e(cgSettings.tag, "Cannot parse .gpx file as GPX " + version + ": could not parse XML - " + e.toString());
- }
- return parsed ? search.getCurrentId() : null;
- }
-
- private UUID parse(final File file, final Handler handlerIn) {
- if (file == null) {
- return null;
- }
-
- FileInputStream fis = null;
- UUID result = null;
- try {
- fis = new FileInputStream(file);
- result = parse(fis, handlerIn);
- } catch (FileNotFoundException e) {
- Log.e(cgSettings.tag, "Cannot parse .gpx file " + file.getAbsolutePath() + " as GPX " + version + ": file not found!");
- }
- try {
- if (fis != null) {
- fis.close();
- }
- } catch (IOException e) {
- Log.e(cgSettings.tag, "Error after parsing .gpx file " + file.getAbsolutePath() + " as GPX " + version + ": could not close file!");
- }
- return result;
- }
-
- protected abstract Element getCacheParent(Element waypoint);
-
- protected static String validate(String input) {
- if ("nil".equalsIgnoreCase(input)) {
- return "";
- }
- return input.trim();
- }
-
- private void setType(String parsedString) {
- final String knownType = cgBase.cacheTypes.get(parsedString);
- if (knownType != null) {
- cache.type = knownType;
- }
- else {
- if (StringUtils.isBlank(cache.type)) {
- cache.type = "mystery"; // default for not recognized types
- }
- }
- }
-
- private void findGeoCode(final String input) {
- if (input == null || StringUtils.isNotBlank(cache.geocode)) {
- return;
- }
- final Matcher matcherGeocode = patternGeocode.matcher(input);
- if (matcherGeocode.find()) {
- if (matcherGeocode.groupCount() > 0) {
- final String geocode = matcherGeocode.group(1);
- if (ConnectorFactory.canHandle(geocode)) {
- cache.geocode = geocode;
- }
- }
- }
- }
-
- private void resetCache() {
- type = null;
- sym = null;
- name = null;
- desc = null;
- cmt = null;
-
- cache = new cgCache();
- for (int i = 0; i < userData.length; i++) {
- userData[i] = null;
- }
- }
-
- public static UUID parseGPX(cgeoapplication app, File file, int listId, Handler handler) {
- final cgSearch search = new cgSearch();
- UUID searchId = null;
-
- try {
- GPXParser parser = new GPX10Parser(app, listId, search);
- searchId = parser.parse(file, handler);
- if (searchId == null) {
- parser = new GPX11Parser(app, listId, search);
- searchId = parser.parse(file, handler);
- }
- } catch (Exception e) {
- Log.e(cgSettings.tag, "cgBase.parseGPX: " + e.toString());
- }
-
- Log.i(cgSettings.tag, "Caches found in .gpx file: " + app.getCount(searchId));
-
- return search.getCurrentId();
- }
+ gcCache.getChild(nsGC, "difficulty").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ try {
+ cache.difficulty = new Float(body);
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse difficulty: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.cache.terrain
+ gcCache.getChild(nsGC, "terrain").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ try {
+ cache.terrain = new Float(body);
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse terrain: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.cache.country
+ gcCache.getChild(nsGC, "country").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String country) {
+ if (StringUtils.isBlank(cache.location)) {
+ cache.location = validate(country);
+ } else {
+ cache.location = cache.location + ", " + country.trim();
+ }
+ }
+ });
+
+ // waypoint.cache.state
+ gcCache.getChild(nsGC, "state").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String state) {
+ if (StringUtils.isBlank(cache.location)) {
+ cache.location = validate(state);
+ } else {
+ cache.location = state.trim() + ", " + cache.location;
+ }
+ }
+ });
+
+ // waypoint.cache.encoded_hints
+ gcCache.getChild(nsGC, "encoded_hints").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String encoded) {
+ cache.hint = validate(encoded);
+ }
+ });
+
+ gcCache.getChild(nsGC, "short_description").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String shortDesc) {
+ cache.shortdesc = validate(shortDesc);
+ }
+ });
+
+ gcCache.getChild(nsGC, "long_description").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String desc) {
+ cache.description = validate(desc);
+ }
+ });
+
+ // waypoint.cache.travelbugs
+ final Element gcTBs = gcCache.getChild(nsGC, "travelbugs");
+
+ // waypoint.cache.travelbugs.travelbug
+ gcTBs.getChild(nsGC, "travelbug").setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ trackable = new cgTrackable();
+
+ try {
+ if (attrs.getIndex("ref") > -1) {
+ trackable.geocode = attrs.getValue("ref").toUpperCase();
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+ });
+
+ // waypoint.cache.travelbug
+ final Element gcTB = gcTBs.getChild(nsGC, "travelbug");
+
+ gcTB.setEndElementListener(new EndElementListener() {
+
+ @Override
+ public void end() {
+ if (StringUtils.isNotBlank(trackable.geocode) && StringUtils.isNotBlank(trackable.name)) {
+ if (cache.inventory == null) {
+ cache.inventory = new ArrayList<cgTrackable>();
+ }
+ cache.inventory.add(trackable);
+ }
+ }
+ });
+
+ // waypoint.cache.travelbugs.travelbug.name
+ gcTB.getChild(nsGC, "name").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String tbName) {
+ trackable.name = validate(tbName);
+ }
+ });
+
+ // waypoint.cache.logs
+ final Element gcLogs = gcCache.getChild(nsGC, "logs");
+
+ // waypoint.cache.log
+ final Element gcLog = gcLogs.getChild(nsGC, "log");
+
+ gcLog.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ log = new cgLog();
+
+ try {
+ if (attrs.getIndex("id") > -1) {
+ log.id = Integer.parseInt(attrs.getValue("id"));
+ }
+ } catch (Exception e) {
+ // nothing
+ }
+ }
+ });
+
+ gcLog.setEndElementListener(new EndElementListener() {
+
+ @Override
+ public void end() {
+ if (StringUtils.isNotBlank(log.log)) {
+ if (cache.logs == null) {
+ cache.logs = new ArrayList<cgLog>();
+ }
+ cache.logs.add(log);
+ }
+ }
+ });
+
+ // waypoint.cache.logs.log.date
+ gcLog.getChild(nsGC, "date").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ try {
+ log.date = parseDate(body).getTime();
+ } catch (Exception e) {
+ Log.w(cgSettings.tag, "Failed to parse log date: " + e.toString());
+ }
+ }
+ });
+
+ // waypoint.cache.logs.log.type
+ gcLog.getChild(nsGC, "type").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String logType = validate(body).toLowerCase();
+ if (cgBase.logTypes0.containsKey(logType)) {
+ log.type = cgBase.logTypes0.get(logType);
+ } else {
+ log.type = cgBase.LOG_NOTE;
+ }
+ }
+ });
+
+ // waypoint.cache.logs.log.finder
+ gcLog.getChild(nsGC, "finder").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String finderName) {
+ log.author = validate(finderName);
+ }
+ });
+
+ // waypoint.cache.logs.log.text
+ gcLog.getChild(nsGC, "text").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String logText) {
+ log.log = validate(logText);
+ }
+ });
+ }
+ boolean parsed = false;
+ try {
+ Xml.parse(stream, Xml.Encoding.UTF_8, root.getContentHandler());
+ parsed = true;
+ } catch (IOException e) {
+ Log.e(cgSettings.tag, "Cannot parse .gpx file as GPX " + version + ": could not read file!");
+ } catch (SAXException e) {
+ Log.e(cgSettings.tag, "Cannot parse .gpx file as GPX " + version + ": could not parse XML - " + e.toString());
+ }
+ return parsed ? search.getCurrentId() : null;
+ }
+
+ private UUID parse(final File file, final Handler handlerIn) {
+ if (file == null) {
+ return null;
+ }
+
+ FileInputStream fis = null;
+ UUID result = null;
+ try {
+ fis = new FileInputStream(file);
+ result = parse(fis, handlerIn);
+ } catch (FileNotFoundException e) {
+ Log.e(cgSettings.tag, "Cannot parse .gpx file " + file.getAbsolutePath() + " as GPX " + version + ": file not found!");
+ }
+ try {
+ if (fis != null) {
+ fis.close();
+ }
+ } catch (IOException e) {
+ Log.e(cgSettings.tag, "Error after parsing .gpx file " + file.getAbsolutePath() + " as GPX " + version + ": could not close file!");
+ }
+ return result;
+ }
+
+ protected abstract Element getCacheParent(Element waypoint);
+
+ protected static String validate(String input) {
+ if ("nil".equalsIgnoreCase(input)) {
+ return "";
+ }
+ return input.trim();
+ }
+
+ private void setType(String parsedString) {
+ final String knownType = cgBase.cacheTypes.get(parsedString);
+ if (knownType != null) {
+ cache.type = knownType;
+ }
+ else {
+ if (StringUtils.isBlank(cache.type)) {
+ cache.type = "mystery"; // default for not recognized types
+ }
+ }
+ }
+
+ private void findGeoCode(final String input) {
+ if (input == null || StringUtils.isNotBlank(cache.geocode)) {
+ return;
+ }
+ final Matcher matcherGeocode = patternGeocode.matcher(input);
+ if (matcherGeocode.find()) {
+ if (matcherGeocode.groupCount() > 0) {
+ final String geocode = matcherGeocode.group(1);
+ if (ConnectorFactory.canHandle(geocode)) {
+ cache.geocode = geocode;
+ }
+ }
+ }
+ }
+
+ private void resetCache() {
+ type = null;
+ sym = null;
+ name = null;
+ desc = null;
+ cmt = null;
+
+ cache = new cgCache();
+ for (int i = 0; i < userData.length; i++) {
+ userData[i] = null;
+ }
+ }
+
+ public static UUID parseGPX(cgeoapplication app, File file, int listId, Handler handler) {
+ final cgSearch search = new cgSearch();
+ UUID searchId = null;
+
+ try {
+ GPXParser parser = new GPX10Parser(app, listId, search);
+ searchId = parser.parse(file, handler);
+ if (searchId == null) {
+ parser = new GPX11Parser(app, listId, search);
+ searchId = parser.parse(file, handler);
+ }
+ } catch (Exception e) {
+ Log.e(cgSettings.tag, "cgBase.parseGPX: " + e.toString());
+ }
+
+ Log.i(cgSettings.tag, "Caches found in .gpx file: " + app.getCount(searchId));
+
+ return search.getCurrentId();
+ }
}