package cgeo.geocaching.files; import cgeo.geocaching.cgBase; import cgeo.geocaching.cgCache; import cgeo.geocaching.cgCacheWrap; import cgeo.geocaching.cgCoord; import cgeo.geocaching.cgSearch; import cgeo.geocaching.cgSettings; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.geopoint.Geopoint; import org.apache.commons.lang3.StringUtils; import android.os.Handler; import android.util.Log; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class LocParser extends FileParser { private static final Pattern patternGeocode = Pattern .compile("name id=\"([^\"]+)\""); private static final Pattern patternLat = Pattern .compile("lat=\"([^\"]+)\""); private static final Pattern patternLon = Pattern .compile("lon=\"([^\"]+)\""); // premium only >> private static final Pattern patternDifficulty = Pattern .compile("([^<]+)"); private static final Pattern patternTerrain = Pattern .compile("([^<]+)"); private static final Pattern patternContainer = Pattern .compile("([^<]+)"); private static final Pattern patternName = Pattern.compile("CDATA\\[([^\\]]+)\\]"); public static void parseLoc(final cgCacheWrap caches, final String fileContent) { final Map cidCoords = parseCoordinates(fileContent); // save found cache coordinates for (cgCache cache : caches.cacheList) { if (cidCoords.containsKey(cache.geocode)) { cgCoord coord = cidCoords.get(cache.geocode); copyCoordToCache(coord, cache); } } } private static void copyCoordToCache(final cgCoord coord, final cgCache cache) { cache.coords = coord.coords; cache.difficulty = coord.difficulty; cache.terrain = coord.terrain; cache.size = coord.size; cache.geocode = coord.geocode.toUpperCase(); if (StringUtils.isBlank(cache.name)) { cache.name = coord.name; } } private static Map parseCoordinates( final String fileContent) { final Map coords = new HashMap(); if (StringUtils.isBlank(fileContent)) { return coords; } // >> premium only final String[] points = fileContent.split(""); // parse coordinates for (String pointString : points) { final cgCoord pointCoord = new cgCoord(); final Matcher matcherGeocode = patternGeocode.matcher(pointString); if (matcherGeocode.find()) { String geocode = matcherGeocode.group(1).trim().toUpperCase(); pointCoord.name = geocode; pointCoord.geocode = geocode; } final Matcher matcherName = patternName.matcher(pointString); if (matcherName.find()) { String name = matcherName.group(1).trim(); int pos = name.indexOf(" by "); if (pos > 0) { name = name.substring(0, pos).trim(); } pointCoord.name = name; } final Matcher matcherLat = patternLat.matcher(pointString); final Matcher matcherLon = patternLon.matcher(pointString); if (matcherLat.find() && matcherLon.find()) { final Map tmpLat = cgBase.parseCoordinate(matcherLat.group(1).trim(), "lat"); final Map tmpLon = cgBase.parseCoordinate(matcherLon.group(1).trim(), "lon"); pointCoord.coords = new Geopoint((Double) tmpLat.get("coordinate"), (Double) tmpLon.get("coordinate")); } final Matcher matcherDifficulty = patternDifficulty.matcher(pointString); if (matcherDifficulty.find()) { pointCoord.difficulty = new Float(matcherDifficulty.group(1) .trim()); } final Matcher matcherTerrain = patternTerrain.matcher(pointString); if (matcherTerrain.find()) { pointCoord.terrain = new Float(matcherTerrain.group(1).trim()); } final Matcher matcherContainer = patternContainer.matcher(pointString); if (matcherContainer.find()) { final int size = Integer.parseInt(matcherContainer.group(1) .trim()); if (size == 1) { pointCoord.size = "not chosen"; } else if (size == 2) { pointCoord.size = "micro"; } else if (size == 3) { pointCoord.size = "regular"; } else if (size == 4) { pointCoord.size = "large"; } else if (size == 5) { pointCoord.size = "virtual"; } else if (size == 6) { pointCoord.size = "other"; } else if (size == 8) { pointCoord.size = "small"; } else { pointCoord.size = "unknown"; } } if (StringUtils.isNotBlank(pointCoord.geocode)) { coords.put(pointCoord.geocode, pointCoord); } } Log.i(cgSettings.tag, "Coordinates found in .loc file: " + coords.size()); return coords; } public static UUID parseLoc(cgeoapplication app, File file, int listId, Handler handler) { cgSearch search = new cgSearch(); UUID searchId = null; try { Map coords = parseCoordinates(readFile(file).toString()); final cgCacheWrap caches = new cgCacheWrap(); for (Entry entry : coords.entrySet()) { cgCoord coord = entry.getValue(); if (StringUtils.isBlank(coord.geocode) || StringUtils.isBlank(coord.name)) { continue; } cgCache cache = new cgCache(); copyCoordToCache(coord, cache); caches.cacheList.add(cache); fixCache(cache); cache.reason = listId; cache.detailed = false; app.addCacheToSearch(search, cache); } caches.totalCnt = caches.cacheList.size(); showFinishedMessage(handler, search); } 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(); } }