2013-04-18 23:35:02 +02:00
|
|
|
package net.osmand.osm.edit;
|
|
|
|
|
2015-07-07 19:58:45 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import net.osmand.data.Amenity;
|
|
|
|
import net.osmand.data.AmenityType;
|
|
|
|
import net.osmand.data.Building;
|
|
|
|
import net.osmand.data.City;
|
2013-04-18 23:35:02 +02:00
|
|
|
import net.osmand.data.City.CityType;
|
2015-07-07 19:58:45 +02:00
|
|
|
import net.osmand.data.LatLon;
|
|
|
|
import net.osmand.data.MapObject;
|
|
|
|
import net.osmand.data.TransportStop;
|
2015-02-18 23:21:57 +01:00
|
|
|
import net.osmand.osm.MapPoiTypes;
|
2013-04-18 23:35:02 +02:00
|
|
|
import net.osmand.osm.MapRenderingTypes;
|
2015-02-18 23:21:57 +01:00
|
|
|
import net.osmand.osm.PoiCategory;
|
2015-07-07 19:58:45 +02:00
|
|
|
import net.osmand.osm.edit.Entity.EntityType;
|
2013-04-18 23:35:02 +02:00
|
|
|
import net.osmand.osm.edit.OSMSettings.OSMTagKey;
|
|
|
|
import net.osmand.util.Algorithms;
|
|
|
|
|
|
|
|
public class EntityParser {
|
|
|
|
|
2015-07-07 19:58:45 +02:00
|
|
|
public static void parseMapObject(MapObject mo, Entity e, Map<String, String> tags) {
|
2013-04-18 23:35:02 +02:00
|
|
|
mo.setId(e.getId());
|
|
|
|
if(mo instanceof Amenity) {
|
2015-07-07 19:58:45 +02:00
|
|
|
mo.setId((e.getId() << 1) + ((EntityType.valueOf(e) == EntityType.NODE) ? 0 : 1));
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
if (mo.getName().length() == 0) {
|
2015-07-07 19:58:45 +02:00
|
|
|
mo.setName(tags.get(OSMTagKey.NAME.getValue()));
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
2015-06-29 17:26:32 +02:00
|
|
|
if (mo.getEnName(false).length() == 0) {
|
2015-07-07 19:58:45 +02:00
|
|
|
mo.setEnName(tags.get(OSMTagKey.NAME_EN.getValue()));
|
2015-06-29 17:26:32 +02:00
|
|
|
}
|
2015-07-07 19:58:45 +02:00
|
|
|
for(String ts : tags.keySet()) {
|
2015-06-30 13:16:01 +02:00
|
|
|
if(ts.startsWith("name:") && !ts.equals(OSMTagKey.NAME_EN.getValue())) {
|
2015-07-07 19:58:45 +02:00
|
|
|
mo.setName(ts.substring(("name:").length()), tags.get(ts));
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
}
|
2015-06-29 17:26:32 +02:00
|
|
|
if (mo.getName().length() == 0) {
|
|
|
|
mo.setName(mo.getEnName(false));
|
|
|
|
}
|
2013-04-18 23:35:02 +02:00
|
|
|
if (mo.getLocation() == null) {
|
2015-05-13 17:02:53 +02:00
|
|
|
LatLon l = null;
|
|
|
|
if (mo instanceof Building) {
|
|
|
|
l = findOnlyOneEntrance(e);
|
|
|
|
}
|
|
|
|
if (l == null) {
|
|
|
|
l = OsmMapUtils.getCenter(e);
|
|
|
|
}
|
2013-04-18 23:35:02 +02:00
|
|
|
if (l != null) {
|
|
|
|
mo.setLocation(l.getLatitude(), l.getLongitude());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mo.getName().length() == 0) {
|
2015-07-07 19:58:45 +02:00
|
|
|
setNameFromOperator(mo, tags);
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
if (mo.getName().length() == 0) {
|
2015-07-07 19:58:45 +02:00
|
|
|
setNameFromRef(mo, tags);
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-13 17:02:53 +02:00
|
|
|
/**
|
|
|
|
* Finds the LatLon of a main entrance point. Main entrance here is the only entrance with value 'main'. If there is
|
|
|
|
* no main entrances, but there is only one entrance of any kind in given building, it is returned.
|
|
|
|
*
|
|
|
|
* @param e building entity
|
|
|
|
* @return main entrance point location or {@code null} if no entrance found or more than one entrance
|
|
|
|
*/
|
|
|
|
private static LatLon findOnlyOneEntrance(Entity e) {
|
|
|
|
if (e instanceof Node) {
|
|
|
|
return e.getLatLon();
|
|
|
|
}
|
|
|
|
List<Node> nodes = null;
|
|
|
|
if (e instanceof Way) {
|
|
|
|
nodes = ((Way) e).getNodes();
|
|
|
|
} else if (e instanceof Relation) {
|
2015-05-13 20:24:52 +02:00
|
|
|
nodes = new ArrayList<Node>();
|
2015-05-13 17:02:53 +02:00
|
|
|
for (Entity member : ((Relation) e).getMembers(null)) {
|
|
|
|
if (member instanceof Way) {
|
|
|
|
nodes.addAll(((Way) member).getNodes());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nodes != null) {
|
|
|
|
int entrancesCount = 0;
|
|
|
|
Node mainEntrance = null;
|
|
|
|
Node lastEntrance = null;
|
|
|
|
|
|
|
|
for (Node node : nodes) {
|
2015-07-07 19:58:45 +02:00
|
|
|
String entrance = node.getTag(OSMTagKey.ENTRANCE.getValue());
|
2015-05-13 17:02:53 +02:00
|
|
|
if (entrance != null && !"no".equals(entrance)) {
|
|
|
|
if ("main".equals(entrance)) {
|
|
|
|
// main entrance should be only one
|
|
|
|
if (mainEntrance != null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
mainEntrance = node;
|
|
|
|
}
|
|
|
|
entrancesCount++;
|
|
|
|
lastEntrance = node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mainEntrance != null) {
|
|
|
|
return mainEntrance.getLatLon();
|
|
|
|
}
|
|
|
|
if (entrancesCount == 1) {
|
|
|
|
return lastEntrance.getLatLon();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2015-07-07 19:58:45 +02:00
|
|
|
private static void setNameFromRef(MapObject mo, Map<String, String> tags) {
|
|
|
|
String ref = tags.get(OSMTagKey.REF.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
if(ref != null){
|
|
|
|
mo.setName(ref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-07 19:58:45 +02:00
|
|
|
private static void setNameFromOperator(MapObject mo, Map<String, String> tags) {
|
|
|
|
String op = tags.get(OSMTagKey.OPERATOR.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
if (op == null)
|
|
|
|
return;
|
2015-07-07 19:58:45 +02:00
|
|
|
String ref = tags.get(OSMTagKey.REF.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
if (ref != null)
|
|
|
|
op += " [" + ref + "]";
|
|
|
|
mo.setName(op);
|
|
|
|
}
|
|
|
|
|
2015-07-07 19:58:45 +02:00
|
|
|
public static Amenity parseAmenity(Entity entity, Map<String, String> tagValues, PoiCategory type, String subtype,
|
2013-11-30 20:44:07 +01:00
|
|
|
MapRenderingTypes types) {
|
2013-04-18 23:35:02 +02:00
|
|
|
Amenity am = new Amenity();
|
2015-07-07 19:58:45 +02:00
|
|
|
parseMapObject(am, entity, tagValues);
|
2013-04-18 23:35:02 +02:00
|
|
|
am.setType(type);
|
|
|
|
am.setSubType(subtype);
|
2015-02-18 23:21:57 +01:00
|
|
|
AmenityType at = AmenityType.findOrCreateTypeNoReg(type.getKeyName());
|
|
|
|
am.setAdditionalInfo(types.getAmenityAdditionalInfo(tagValues, at, subtype));
|
2015-07-07 19:58:45 +02:00
|
|
|
String wbs = getWebSiteURL(tagValues);
|
2015-02-02 09:24:59 +01:00
|
|
|
if(wbs != null) {
|
|
|
|
am.setAdditionalInfo("website", wbs);
|
|
|
|
}
|
2013-11-13 14:13:48 +01:00
|
|
|
return am;
|
|
|
|
}
|
2015-07-09 14:14:52 +02:00
|
|
|
|
|
|
|
public static Amenity parseAmenity(Entity entity, Map<String, String> tagValues, PoiCategory type, String subtype,
|
|
|
|
MapPoiTypes types) {
|
|
|
|
Amenity am = new Amenity();
|
|
|
|
parseMapObject(am, entity, tagValues);
|
|
|
|
am.setType(type);
|
|
|
|
am.setSubType(subtype);
|
|
|
|
AmenityType at = AmenityType.findOrCreateTypeNoReg(type.getKeyName());
|
|
|
|
am.setAdditionalInfo(types.getAmenityAdditionalInfo(tagValues, at, subtype));
|
|
|
|
String wbs = getWebSiteURL(tagValues);
|
|
|
|
if(wbs != null) {
|
|
|
|
am.setAdditionalInfo("website", wbs);
|
|
|
|
}
|
|
|
|
return am;
|
|
|
|
}
|
2013-11-13 14:13:48 +01:00
|
|
|
|
2013-11-24 01:24:16 +01:00
|
|
|
|
2013-11-13 14:13:48 +01:00
|
|
|
|
2015-07-07 19:58:45 +02:00
|
|
|
private static String getWebSiteURL(Map<String, String> tagValues) {
|
|
|
|
String siteUrl = tagValues.get(OSMTagKey.WIKIPEDIA.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
if (siteUrl != null) {
|
|
|
|
if (!siteUrl.startsWith("http://")) { //$NON-NLS-1$
|
|
|
|
int i = siteUrl.indexOf(':');
|
|
|
|
if (i == -1) {
|
|
|
|
siteUrl = "http://en.wikipedia.org/wiki/" + siteUrl; //$NON-NLS-1$
|
|
|
|
} else {
|
|
|
|
siteUrl = "http://" + siteUrl.substring(0, i) + ".wikipedia.org/wiki/" + siteUrl.substring(i + 1); //$NON-NLS-1$ //$NON-NLS-2$
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2015-07-07 19:58:45 +02:00
|
|
|
siteUrl = tagValues.get(OSMTagKey.WEBSITE.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
if (siteUrl == null) {
|
2015-07-07 19:58:45 +02:00
|
|
|
siteUrl = tagValues.get(OSMTagKey.URL.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
if (siteUrl == null) {
|
2015-07-07 19:58:45 +02:00
|
|
|
siteUrl = tagValues.get(OSMTagKey.CONTACT_WEBSITE.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-14 20:25:57 +02:00
|
|
|
if (siteUrl != null && !siteUrl.startsWith("http://") && !siteUrl.startsWith("https://")) {
|
2013-04-18 23:35:02 +02:00
|
|
|
siteUrl = "http://" + siteUrl;
|
|
|
|
}
|
|
|
|
}
|
2013-11-13 14:13:48 +01:00
|
|
|
return siteUrl;
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
|
2015-07-09 14:14:52 +02:00
|
|
|
|
|
|
|
public static List<Amenity> parseAmenities(MapPoiTypes poiTypes, Entity entity, Map<String, String> tags,List<Amenity> amenitiesList) {
|
|
|
|
amenitiesList.clear();
|
|
|
|
// it could be collection of amenities
|
|
|
|
boolean relation = entity instanceof Relation;
|
|
|
|
boolean purerelation = relation && !"multipolygon".equals(tags.get("type"));
|
|
|
|
boolean hasName = !Algorithms.isEmpty(tags.get("name"));
|
|
|
|
for (Map.Entry<String, String> e : tags.entrySet()) {
|
|
|
|
AmenityType type = purerelation ? poiTypes.getAmenityTypeForRelation(e.getKey(), e.getValue(), hasName)
|
|
|
|
: poiTypes.getAmenityType(e.getKey(), e.getValue(), hasName);
|
|
|
|
if (type != null) {
|
|
|
|
String subtype = poiTypes.getAmenitySubtype(e.getKey(), e.getValue());
|
|
|
|
PoiCategory pc = poiTypes.getPoiCategoryByName(type.getCategoryName(), true);
|
|
|
|
Amenity a = parseAmenity(entity, tags, pc, subtype, poiTypes);
|
|
|
|
if (checkAmenitiesToAdd(a, amenitiesList) && !"no".equals(subtype)) {
|
|
|
|
amenitiesList.add(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return amenitiesList;
|
|
|
|
}
|
|
|
|
|
2013-04-18 23:35:02 +02:00
|
|
|
public static List<Amenity> parseAmenities(MapRenderingTypes renderingTypes,
|
2015-07-07 19:58:45 +02:00
|
|
|
MapPoiTypes poiTypes, Entity entity, Map<String, String> tags, List<Amenity> amenitiesList){
|
2013-11-30 19:07:47 +01:00
|
|
|
amenitiesList.clear();
|
2013-04-18 23:35:02 +02:00
|
|
|
// it could be collection of amenities
|
|
|
|
boolean relation = entity instanceof Relation;
|
2015-07-07 19:58:45 +02:00
|
|
|
Collection<Map<String, String>> it = renderingTypes.splitTagsIntoDifferentObjects(tags);
|
|
|
|
for(Map<String, String> stags : it) {
|
|
|
|
if (!stags.isEmpty()) {
|
|
|
|
boolean purerelation = relation && !"multipolygon".equals(stags.get("type"));
|
|
|
|
boolean hasName = !Algorithms.isEmpty(stags.get("name"));
|
|
|
|
for (Map.Entry<String, String> e : stags.entrySet()) {
|
2015-01-06 21:45:58 +01:00
|
|
|
AmenityType type = purerelation ? renderingTypes.getAmenityTypeForRelation(e.getKey(), e.getValue(), hasName)
|
|
|
|
: renderingTypes.getAmenityType(e.getKey(), e.getValue(), hasName );
|
2013-11-30 19:07:47 +01:00
|
|
|
if (type != null) {
|
|
|
|
String subtype = renderingTypes.getAmenitySubtype(e.getKey(), e.getValue());
|
2015-02-18 23:21:57 +01:00
|
|
|
PoiCategory pc = poiTypes.getPoiCategoryByName(type.getCategoryName(), true);
|
2015-07-07 19:58:45 +02:00
|
|
|
Amenity a = parseAmenity(entity, stags, pc, subtype, renderingTypes);
|
2013-11-30 19:07:47 +01:00
|
|
|
if (checkAmenitiesToAdd(a, amenitiesList) && !"no".equals(subtype)) {
|
|
|
|
amenitiesList.add(a);
|
|
|
|
}
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return amenitiesList;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean checkAmenitiesToAdd(Amenity a, List<Amenity> amenitiesList){
|
|
|
|
// check amenity for duplication
|
|
|
|
for(Amenity b : amenitiesList){
|
|
|
|
if(b.getType() == a.getType() && Algorithms.objectEquals(a.getSubType(), b.getSubType())){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Building parseBuilding(Entity e){
|
|
|
|
Building b = new Building();
|
2015-07-07 19:58:45 +02:00
|
|
|
parseMapObject(b, e, e.getTags());
|
2013-04-18 23:35:02 +02:00
|
|
|
// try to extract postcode
|
2015-07-07 19:58:45 +02:00
|
|
|
String p = e.getTag(OSMTagKey.ADDR_POSTCODE.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
if(p == null) {
|
2015-07-07 19:58:45 +02:00
|
|
|
p = e.getTag(OSMTagKey.POSTAL_CODE.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
b.setPostcode(p);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static City parseCity(Node el) {
|
2015-07-07 19:58:45 +02:00
|
|
|
return parseCity(el, CityType.valueFromString(el.getTag(OSMTagKey.PLACE.getValue())));
|
2013-04-18 23:35:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static City parseCity(Entity el, CityType t) {
|
|
|
|
if(t == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
City c = new City(t);
|
2015-07-07 19:58:45 +02:00
|
|
|
parseMapObject(c, el, el.getTags());
|
|
|
|
String isin = el.getTag(OSMTagKey.IS_IN.getValue());
|
2013-04-18 23:35:02 +02:00
|
|
|
isin = isin != null ? isin.toLowerCase() : null;
|
|
|
|
c.setIsin(isin);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static OsmTransportRoute parserRoute(Relation r, String ref){
|
|
|
|
OsmTransportRoute rt = new OsmTransportRoute();
|
2015-07-07 19:58:45 +02:00
|
|
|
parseMapObject(rt, r, r.getTags());
|
2013-04-18 23:35:02 +02:00
|
|
|
rt.setRef(ref);
|
|
|
|
return rt;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static TransportStop parseTransportStop(Entity e){
|
|
|
|
TransportStop st = new TransportStop();
|
2015-07-07 19:58:45 +02:00
|
|
|
parseMapObject(st, e, e.getTags());
|
2013-04-18 23:35:02 +02:00
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|