package net.osmand.osm.edit; import net.osmand.data.LatLon; import net.osmand.osm.edit.OSMSettings.OSMTagKey; import net.osmand.util.Algorithms; import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; public abstract class Entity implements Serializable { public enum EntityType { NODE, WAY, RELATION, WAY_BOUNDARY; public static EntityType valueOf(Entity e) { if (e instanceof Node) { return NODE; } else if (e instanceof Way) { return WAY; } else if (e instanceof Relation) { return RELATION; } return null; } } public static class EntityId { private final EntityType type; private final Long id; public EntityId(EntityType type, Long id) { this.type = type; this.id = id; } public static EntityId valueOf(Entity e) { return new EntityId(EntityType.valueOf(e), e.getId()); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @Override public String toString() { return type + " " + id; //$NON-NLS-1$ } public EntityType getType() { return type; } public Long getId() { return id; } public String getOsmUrl() { final String browseUrl = "https://www.openstreetmap.org/browse/"; if (type == EntityType.NODE) return browseUrl + "node/" + id; if (type == EntityType.WAY) return browseUrl + "way/" + id; return null; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; EntityId other = (EntityId) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; return true; } } // lazy initializing private Map<String, String> tags = null; private final long id; private boolean dataLoaded; private int modify; private int version; public static final int MODIFY_UNKNOWN = 0; public static final int MODIFY_DELETED = -1; public static final int MODIFY_MODIFIED = 1; public static final int MODIFY_CREATED = 2; public Entity(long id) { this.id = id; } public Entity(Entity copy, long id) { this.id = id; for (String t : copy.getTagKeySet()) { putTagNoLC(t, copy.getTag(t)); } this.dataLoaded = copy.dataLoaded; } public int getModify() { return modify; } public void setModify(int modify) { this.modify = modify; } public long getId() { return id; } public String removeTag(String key) { if (tags != null) { return tags.remove(key); } return null; } public void removeTags(String... keys) { if (tags != null) { for (String key : keys) { tags.remove(key); } } } public String putTag(String key, String value) { return putTagNoLC(key.toLowerCase(), value); } public String putTagNoLC(String key, String value) { if (tags == null) { tags = new LinkedHashMap<String, String>(); } return tags.put(key, value); } public void replaceTags(Map<String, String> toPut) { tags = new LinkedHashMap<String, String>(toPut); } public String getTag(OSMTagKey key) { return getTag(key.getValue()); } public String getTag(String key) { if (tags == null) { return null; } return tags.get(key); } public Map<String, String> getNameTags() { Map<String, String> result = new LinkedHashMap<String, String>(); for (Map.Entry<String, String> e : tags.entrySet()) { if (e.getKey().startsWith("name:")) { result.put(e.getKey(), e.getValue()); } } return result; } public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } public Map<String, String> getTags() { if (tags == null) { return Collections.emptyMap(); } return Collections.unmodifiableMap(tags); } public Collection<String> getTagKeySet() { if (tags == null) { return Collections.emptyList(); } return tags.keySet(); } public abstract void initializeLinks(Map<EntityId, Entity> entities); /** * @return middle point for entity */ public abstract LatLon getLatLon(); public boolean isVirtual() { return id < 0; } public String getOsmUrl() { return EntityId.valueOf(this).getOsmUrl(); } @Override public String toString() { return EntityId.valueOf(this).toString(); } @Override public int hashCode() { if (id < 0) { return System.identityHashCode(this); } return (int) id; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Entity other = (Entity) obj; if (id != other.id) return false; // virtual are not equal if (id < 0) { return false; } return true; } public Set<String> getIsInNames() { String values = getTag(OSMTagKey.IS_IN); if (values == null) { String city = getTag(OSMTagKey.ADDR_CITY); if(!Algorithms.isEmpty(city)) { return Collections.singleton(city.trim()); } return Collections.emptySet(); } if (values.indexOf(';') != -1) { String[] splitted = values.split(";"); Set<String> set = new HashSet<String>(splitted.length); for (int i = 0; i < splitted.length; i++) { set.add(splitted[i].trim()); } return set; } return Collections.singleton(values.trim()); } public void entityDataLoaded() { this.dataLoaded = true; } public boolean isDataLoaded() { return dataLoaded; } public Map<String, String> getModifiableTags() { if (tags == null) { return Collections.emptyMap(); } return tags; } }