More changes address creation without cityAdminLevel.

Some small refactoring also. Still, the streets are not generated
correctly.
This commit is contained in:
Pavol Zibrita 2011-09-23 11:09:13 +02:00
parent 9a439f2d41
commit 2093ac93dc
9 changed files with 230 additions and 162 deletions

View file

@ -32,7 +32,8 @@ public class BinaryInspector {
public static void main(String[] args) throws IOException {
inspector(args);
// test cases show info
inspector(new String[]{"/home/victor/projects/OsmAnd/data/osm-gen/saved/Belarus-newzooms-new-rt.obf"});
//inspector(new String[]{"/home/victor/projects/OsmAnd/data/osm-gen/saved/Belarus-newzooms-new-rt.obf"});
//inspector(new String[]{"-v","C:\\Users\\tpd\\osmand\\Slovakia.obf "});
// test case extract parts

View file

@ -69,7 +69,7 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
private DataTileManager<City> cityVillageManager = new DataTileManager<City>(13);
private DataTileManager<City> cityManager = new DataTileManager<City>(10);
private List<Relation> postalCodeRelations = new ArrayList<Relation>();
private Map<City, Boundary> cityBoundaries = new LinkedHashMap<City, Boundary>();
private Map<City, Boundary> cityBoundaries = new HashMap<City, Boundary>();
private TLongHashSet visitedBoundaryWays = new TLongHashSet();
private boolean normalizeStreets;
@ -81,7 +81,7 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
// TODO
Connection mapConnection;
DBStreetDAO streetDAO;
public class DBStreetDAO
{
protected void writeStreetWayNodes(Set<Long> streetIds, Way way) throws SQLException {
@ -154,7 +154,7 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
public class CachedDBStreetDAO extends DBStreetDAO
{
private Map<String, Long> addressStreetLocalMap = new LinkedHashMap<String, Long>();
private Map<String, Long> addressStreetLocalMap = new HashMap<String, Long>();
private TLongHashSet addressBuildingLocalSet = new TLongHashSet();
private TLongHashSet addressStreetNodeLocalSet = new TLongHashSet();
@ -250,76 +250,95 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
}
public void indexBoundariesRelation(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (isBoundary(e)) {
int adminLevel = 8;
try {
String tag = e.getTag(OSMTagKey.ADMIN_LEVEL);
if (tag == null) {
return;
Boundary boundary = extractBoundary(e, ctx);
if (boundary != null && boundary.getAdminLevel() >= 4 && boundary.getCenterPoint() != null && !Algoritms.isEmpty(boundary.getName())) {
LatLon boundaryCenter = boundary.getCenterPoint();
List<City> citiesToSearch = new ArrayList<City>();
citiesToSearch.addAll(cityManager.getClosestObjects(boundaryCenter.getLatitude(), boundaryCenter.getLongitude(), 3));
citiesToSearch.addAll(cityVillageManager.getClosestObjects(boundaryCenter.getLatitude(), boundaryCenter.getLongitude(), 3));
List<City> cityFound = new ArrayList<City>();
String boundaryName = boundary.getName().toLowerCase();
for (City c : citiesToSearch) {
if (boundary.containsPoint(c.getLocation())) {
if (boundaryName.equalsIgnoreCase(c.getName())) {
cityFound.add(c);
break;
}
}
adminLevel = Integer.parseInt(tag);
} catch (NumberFormatException ex) {
return;
}
if (adminLevel < 4) {
return;
}
Boundary boundary = extractBoundary(e, ctx);
if (boundary != null && boundary.getCenterPoint() != null && !Algoritms.isEmpty(boundary.getName())) {
boundary.setAdminLevel(adminLevel);
LatLon point = boundary.getCenterPoint();
City cityFound = null;
List<City> citiesToSearch = new ArrayList<City>();
citiesToSearch.addAll(cityManager.getClosestObjects(point.getLatitude(), point.getLongitude(), 3));
citiesToSearch.addAll(cityVillageManager.getClosestObjects(point.getLatitude(), point.getLongitude(), 3));
String boundaryName = boundary.getName().toLowerCase();
if (cityFound.isEmpty()) {
// try to find same name in the middle
for (City c : citiesToSearch) {
if (boundary.containsPoint(c.getLocation())) {
if (boundaryName.equalsIgnoreCase(c.getName())) {
cityFound = c;
String lower = c.getName().toLowerCase();
if (boundaryName.startsWith(lower) || boundaryName.endsWith(lower) || boundaryName.contains(" " + lower + " ")) {
cityFound.add(c);
break;
}
}
}
if (cityFound != null) {
// try to find same name in the middle
for (City c : citiesToSearch) {
if (boundary.containsPoint(c.getLocation())) {
String lower = c.getName().toLowerCase();
if (boundaryName.startsWith(lower) || boundaryName.endsWith(lower) || boundaryName.contains(" " + lower + " ")) {
cityFound = c;
break;
}
}
}
}
if (cityFound != null) {
putCityBoundary(boundary, cityFound);
}
}
// if (cityFound.isEmpty()) {
// try to find closes city to the boundary center
// double minDist = Double.MAX_VALUE;
// City closestCity = null;
// for (City c : citiesToSearch) {
// if (boundary.containsPoint(c.getLocation())) {
//// double dist = MapUtils.getDistance(boundaryCenter, c.getLocation());
//// if (dist < minDist) {
//// dist = minDist;
//// closestCity = c;
//// }
// cityFound.add(c);
// }
// }
// cityFound = closestCity;
// }
if (!cityFound.isEmpty()) {
//we can have more cities in one boundary!! (suburbs...)
putCityBoundary(boundary, cityFound);
}
}
}
private void putCityBoundary(Boundary boundary, City c) {
final Boundary oldBoundary = cityBoundaries.get(c);
if (oldBoundary != null) {
// try to found the biggest area (not small center district)
if (oldBoundary.getAdminLevel() > boundary.getAdminLevel()) {
cityBoundaries.put(c, boundary);
} else if(boundary.getName().equalsIgnoreCase(c.getName()) &&
!oldBoundary.getName().equalsIgnoreCase(c.getName())){
cityBoundaries.put(c, boundary);
} else if(oldBoundary.getAdminLevel() == boundary.getAdminLevel() &&
oldBoundary != boundary && boundary.getName().equalsIgnoreCase(oldBoundary.getName())){
if(!oldBoundary.isClosedWay() && !boundary.isClosedWay()){
oldBoundary.getInnerWays().addAll(boundary.getInnerWays());
oldBoundary.getOuterWays().addAll(boundary.getOuterWays());
}
private int extractBoundaryAdminLevel(Entity e) {
int adminLevel = -1;
try {
String tag = e.getTag(OSMTagKey.ADMIN_LEVEL);
if (tag == null) {
return adminLevel;
}
return Integer.parseInt(tag);
} catch (NumberFormatException ex) {
return adminLevel;
}
}
private void putCityBoundary(Boundary boundary, List<City> cities) {
for (City cityFound : cities) {
final Boundary oldBoundary = cityBoundaries.get(cityFound);
if (oldBoundary != null) {
// try to found the biggest area (not small center district)
if (oldBoundary.getAdminLevel() > boundary.getAdminLevel() && !oldBoundary.getName().equalsIgnoreCase(cityFound.getName())) {
cityBoundaries.put(cityFound, boundary);
System.out.println("City: " + cityFound.getName() + " boundary: " + boundary.getName());
} else if(boundary.getName().equalsIgnoreCase(cityFound.getName()) &&
!oldBoundary.getName().equalsIgnoreCase(cityFound.getName())){
cityBoundaries.put(cityFound, boundary);
System.out.println("City: " + cityFound.getName() + " boundary: " + boundary.getName());
} else if(oldBoundary.getAdminLevel() == boundary.getAdminLevel() &&
oldBoundary != boundary && boundary.getName().equalsIgnoreCase(oldBoundary.getName())){
if(!oldBoundary.isClosedWay() && !boundary.isClosedWay()){
oldBoundary.getInnerWays().addAll(boundary.getInnerWays());
oldBoundary.getOuterWays().addAll(boundary.getOuterWays());
}
}
} else {
cityBoundaries.put(cityFound, boundary);
System.out.println("City: " + cityFound.getName() + " boundary: " + boundary.getName());
}
} else {
cityBoundaries.put(c, boundary);
}
}
@ -331,14 +350,13 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
if (isBoundary(e)) {
Boundary boundary = null;
if (e instanceof Relation) {
Relation i = (Relation) e;
ctx.loadEntityData(i, true);
boundary = new Boundary(true);
if (i.getTag(OSMTagKey.NAME) != null) {
boundary.setName(i.getTag(OSMTagKey.NAME));
}
boundary.setBoundaryId(i.getId());
Map<Entity, String> entities = i.getMemberEntities();
Relation aRelation = (Relation) e;
ctx.loadEntityData(aRelation);
boundary = new Boundary(true); //TODO here should be true or false ??? or, how it should be computed in this case?
boundary.setName(aRelation.getTag(OSMTagKey.NAME));
boundary.setBoundaryId(aRelation.getId());
boundary.setAdminLevel(extractBoundaryAdminLevel(aRelation));
Map<Entity, String> entities = aRelation.getMemberEntities();
for (Entity es : entities.keySet()) {
if (es instanceof Way) {
boolean inner = "inner".equals(entities.get(es)); //$NON-NLS-1$
@ -362,10 +380,9 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
closed = Algoritms.objectEquals(nodeIds.get(0), nodeIds.get(nodeIds.size() - 1));
}
boundary = new Boundary(closed);
if (e.getTag(OSMTagKey.NAME) != null) {
boundary.setName(e.getTag(OSMTagKey.NAME));
}
boundary.setName(e.getTag(OSMTagKey.NAME));
boundary.setBoundaryId(e.getId());
boundary.setAdminLevel(extractBoundaryAdminLevel(e));
boundary.getOuterWays().add((Way) e);
}
}
@ -385,7 +402,7 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
// try to find appropriate city/street
City c = null;
// load with member ways with their nodes and tags !
ctx.loadEntityData(i, true);
ctx.loadEntityData(i);
Collection<Entity> members = i.getMembers("is_in"); //$NON-NLS-1$
Relation a3 = null;
@ -395,7 +412,7 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
a6 = i;
}
Entity in = members.iterator().next();
ctx.loadEntityData(in, true);
ctx.loadEntityData(in);
if (in instanceof Relation) {
// go one level up for house
if (house) {
@ -403,7 +420,7 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
members = ((Relation) in).getMembers("is_in"); //$NON-NLS-1$
if (!members.isEmpty()) {
in = members.iterator().next();
ctx.loadEntityData(in, true);
ctx.loadEntityData(in);
if (in instanceof Relation) {
a3 = (Relation) in;
}
@ -436,7 +453,7 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
}
}
Set<Long> streetId = registerStreetInCity(name, null, location, (a6.getId() << 2) | 2, Collections.singletonList(c));
Set<Long> streetId = registerStreetInCities(name, null, location, Collections.singletonList(c));
if (streetId == null) {
return;
}
@ -566,13 +583,13 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
return newName.trim();
}
public Set<Long> getStreetInCity(Set<String> isInNames, String name, String nameEn, LatLon location, long initId) throws SQLException {
public Set<Long> getStreetInCity(Set<String> isInNames, String name, String nameEn, LatLon location) throws SQLException {
if (name == null || location == null) {
return Collections.emptySet();
}
name = normalizeStreetName(name);
List<City> result = new ArrayList<City>();
Set<City> result = new HashSet<City>();
List<City> nearestObjects = new ArrayList<City>();
nearestObjects.addAll(cityManager.getClosestObjects(location.getLatitude(),location.getLongitude()));
nearestObjects.addAll(cityVillageManager.getClosestObjects(location.getLatitude(),location.getLongitude()));
@ -588,13 +605,17 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
result.add(city);
}
}
// for (Entry<City,Boundary> cb : cityBoundaries.entrySet()) {
// if (cb.getValue().containsPoint(location)) {
// result.add(cb.getKey());
// }
// }
return registerStreetInCity(name, nameEn, location, initId, result);
return registerStreetInCities(name, nameEn, location, result);
}
private Set<Long> registerStreetInCity(String name, String nameEn, LatLon location, long initId,
List<City> result) throws SQLException {
private Set<Long> registerStreetInCities(String name, String nameEn, LatLon location, Collection<City> result) throws SQLException {
if (result.isEmpty()) {
return null;
}
@ -614,12 +635,12 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
}
}
}
Long foundId = streetDAO.findStreet(name, result.get(0), cityPart);
Long foundId = streetDAO.findStreet(name, city, cityPart);
if (foundId == null) {
insertStreetData(addressStreetStat, initId, name, nameEn, location.getLatitude(), location.getLongitude(), city.getId(),
long streetId = insertStreetData(addressStreetStat, name, nameEn, location.getLatitude(), location.getLongitude(), city.getId(),
cityPart);
streetDAO.insertStreet(addressStreetStat, name, city, cityPart, initId);
foundId = initId;
streetDAO.insertStreet(addressStreetStat, name, city, cityPart, streetId);
foundId = streetId;
}
values.add(foundId);
}
@ -685,22 +706,6 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
return closest;
}
private Set<String> getIsINames(Entity e) {
String values = e.getTag(OSMTagKey.IS_IN);
if (values == null) {
return Collections.emptySet();
}
if (values.indexOf(';') != -1) {
String[] splitted = values.split(";");
Set<String> set = new HashSet<String>();
for (int i = 0; i < splitted.length; i++) {
set.add(splitted[i].trim());
}
return set;
}
return Collections.singleton(values.trim());
}
public void iterateMainEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
// index not only buildings but also nodes that belongs to addr:interpolation ways
if (e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER) != null && e.getTag(OSMTagKey.ADDR_STREET) != null) {
@ -708,13 +713,13 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
// check that building is not registered already
boolean exist = streetDAO.findBuilding(e);
if (!exist) {
ctx.loadEntityData(e, false);
ctx.loadEntityData(e);
LatLon l = e.getLatLon();
Set<Long> idStreet = getStreetInCity(getIsINames(e), e.getTag(OSMTagKey.ADDR_STREET), null, l, (e.getId() << 2));
if (!idStreet.isEmpty()) {
Set<Long> idsOfStreet = getStreetInCity(e.getIsInNames(), e.getTag(OSMTagKey.ADDR_STREET), null, l);
if (!idsOfStreet.isEmpty()) {
Building building = new Building(e);
building.setName(e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER));
streetDAO.writeBuilding(idStreet, building);
streetDAO.writeBuilding(idsOfStreet, building);
}
}
} else if (e instanceof Way /* && OSMSettings.wayForCar(e.getTag(OSMTagKey.HIGHWAY)) */
@ -730,17 +735,17 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
// check that street way is not registered already
if (!exist) {
ctx.loadEntityData(e, false);
ctx.loadEntityData(e);
LatLon l = e.getLatLon();
Set<Long> idStreet = getStreetInCity(getIsINames(e), e.getTag(OSMTagKey.NAME), e.getTag(OSMTagKey.NAME_EN), l, (e.getId() << 2) | 1);
if (!idStreet.isEmpty() && saveAddressWays) {
streetDAO.writeStreetWayNodes(idStreet, (Way) e);
Set<Long> idsOfStreet = getStreetInCity(e.getIsInNames(), e.getTag(OSMTagKey.NAME), e.getTag(OSMTagKey.NAME_EN), l);
if (!idsOfStreet.isEmpty() && saveAddressWays) {
streetDAO.writeStreetWayNodes(idsOfStreet, (Way) e);
}
}
}
if (e instanceof Relation) {
if (e.getTag(OSMTagKey.POSTAL_CODE) != null) {
ctx.loadEntityData(e, false);
ctx.loadEntityData(e);
postalCodeRelations.add((Relation) e);
}
}
@ -757,15 +762,21 @@ public class IndexAddressCreator extends AbstractIndexPartCreator{
}
private void insertStreetData(PreparedStatement addressStreetStat, long id, String name, String nameEn, double latitude,
private long streetIdSequence = 0;
private long insertStreetData(PreparedStatement addressStreetStat, //long id,
String name, String nameEn, double latitude,
double longitude, Long cityId, String cityPart) throws SQLException {
addressStreetStat.setLong(1, id);
long streetId = streetIdSequence++;
// addressStreetStat.setLong(1, id);
addressStreetStat.setLong(1, streetId);
addressStreetStat.setString(4, name);
addressStreetStat.setString(5, nameEn);
addressStreetStat.setDouble(2, latitude);
addressStreetStat.setDouble(3, longitude);
addressStreetStat.setLong(6, cityId);
addressStreetStat.setString(7, cityPart);
return streetId;
}

View file

@ -261,7 +261,7 @@ public class IndexCreator {
// 1. Loading osm file
OsmDbCreator dbCreator = new OsmDbCreator(this);
try {
progress.setGeneralProgress("[35 / 100]"); //$NON-NLS-1$
progress.setGeneralProgress("[15 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.LOADING_FILE") + readFile.getAbsolutePath(), -1); //$NON-NLS-1$
// 1 init database to store temporary data
dbCreator.initDatabase(dialect, dbConn);
@ -311,9 +311,10 @@ public class IndexCreator {
if (DBDialect.NOSQL != dialect) {
Connection dbc = (Connection) dbConn;
final Statement stmt = dbc.createStatement();
allRelations = stmt.executeQuery("select count(*) from relations").getInt(1);
allNodes = stmt.executeQuery("select count(*) from node").getInt(1);
allWays = stmt.executeQuery("select count(*) from ways").getInt(1);
accessor.computeRealCounts(stmt);
allRelations = accessor.getAllRelations();
allNodes = accessor.getAllNodes();
allWays = accessor.getAllWays();
stmt.close();
}
}
@ -419,7 +420,7 @@ public class IndexCreator {
// 3.1 write all cities
if (indexAddress) {
progress.setGeneralProgress("[40 / 100]"); //$NON-NLS-1$
progress.setGeneralProgress("[20 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.INDEX_CITIES"), accessor.getAllNodes()); //$NON-NLS-1$
if (loadFromExistingFile) {
// load cities names
@ -441,7 +442,7 @@ public class IndexCreator {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (indexAddress) {
indexAddressCreator.indexAddressRelation((Relation) e, ctx);
//indexAddressCreator.indexAddressRelation((Relation) e, ctx); streets needs loaded boundaries !!!
indexAddressCreator.indexBoundariesRelation((Relation) e, ctx);
}
if (indexMap) {
@ -459,9 +460,17 @@ public class IndexCreator {
}
});
progress.setGeneralProgress("[45 / 100]"); //$NON-NLS-1$
progress.startTask(Messages.getString("IndexCreator.PREINDEX_ADRESS_MAP"), accessor.getAllRelations()); //$NON-NLS-1$
accessor.iterateOverEntities(progress, EntityType.RELATION, new OsmDbVisitor() {
@Override
public void iterateEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
indexAddressCreator.indexAddressRelation((Relation) e, ctx);
}
});
indexAddressCreator.commitToPutAllCities();
}
}
// 3.3 MAIN iterate over all entities

View file

@ -53,7 +53,7 @@ public class IndexPoiCreator extends AbstractIndexPartCreator {
tempAmenityList = Amenity.parseAmenities(e, tempAmenityList);
if (!tempAmenityList.isEmpty() && poiPreparedStatement != null) {
// load data for way (location etc...)
ctx.loadEntityData(e, false);
ctx.loadEntityData(e);
for (Amenity a : tempAmenityList) {
// do not add that check because it is too much printing for batch creation
// by statistic < 1% creates maps manually

View file

@ -130,7 +130,7 @@ public class IndexTransportCreator extends AbstractIndexPartCreator {
public void visitEntityMainStep(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (e instanceof Relation && e.getTag(OSMTagKey.ROUTE) != null) {
ctx.loadEntityData(e, true);
ctx.loadEntityData(e);
TransportRoute route = indexTransportRoute((Relation) e);
if (route != null) {
insertTransportIntoIndex(route);

View file

@ -84,7 +84,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
private void indexMultiPolygon(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (e instanceof Relation && "multipolygon".equals(e.getTag(OSMTagKey.TYPE))) { //$NON-NLS-1$
ctx.loadEntityData(e, true);
ctx.loadEntityData(e);
Map<Entity, String> entities = ((Relation) e).getMemberEntities();
boolean outerFound = false;
@ -222,7 +222,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
type = MapRenderingTypes.RESTRICTION_ONLY_STRAIGHT_ON;
}
if (type != -1) {
ctx.loadEntityData(e, true);
ctx.loadEntityData(e);
Collection<EntityId> fromL = ((Relation) e).getMemberIds("from"); //$NON-NLS-1$
Collection<EntityId> toL = ((Relation) e).getMemberIds("to"); //$NON-NLS-1$
if (!fromL.isEmpty() && !toL.isEmpty()) {
@ -643,7 +643,7 @@ public class IndexVectorMapCreator extends AbstractIndexPartCreator {
public void iterateMainEntity(Entity e, OsmDbAccessorContext ctx) throws SQLException {
if (e instanceof Way || e instanceof Node) {
// manipulate what kind of way to load
ctx.loadEntityData(e, false);
ctx.loadEntityData(e);
boolean oneway = "-1".equals(e.getTag(OSMTagKey.ONEWAY)); //$NON-NLS-1$
for (int i = 0; i < mapZooms.size(); i++) {
boolean inverse = i == 0 ? oneway : false;

View file

@ -48,6 +48,12 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
private ReadOptions randomAccessOptions;
private DBAccessor accessor;
private PreparedStatement iterateNodes;
private PreparedStatement iterateWays;
private PreparedStatement iterateRelations;
public interface OsmDbVisitor {
@ -77,6 +83,12 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
"from relations r left join tags t on r.id = t.id and t.type = 2 and r.ord = 0 " + //$NON-NLS-1$
"where r.id = ? order by r.ord"); //$NON-NLS-1$
pselectTags = dbConn.prepareStatement("select skeys, value from tags where id = ? and type = ?"); //$NON-NLS-1$
iterateNodes = dbConn.prepareStatement("select n.id, n.latitude, n.longitude, t.skeys, t.value from node n inner join tags t on n.id = t.id and t.type = 0 order by n.id"); //$NON-NLS-1$
iterateWays = dbConn.prepareStatement("select w.id, w.node, w.ord, t.skeys, t.value, n.latitude, n.longitude " + //$NON-NLS-1$
"from ways w left join tags t on w.id = t.id and t.type = 1 and w.ord = 0 inner join node n on w.node = n.id " + //$NON-NLS-1$
"order by w.id, w.ord"); //$NON-NLS-1$
iterateRelations = dbConn.prepareStatement("select r.id, t.skeys, t.value from relations r inner join tags t on t.id = r.id and t.type = 2 and r.ord = 0"); //$NON-NLS-1$
}
}
@ -92,13 +104,17 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
return allWays;
}
public void loadEntityData(Entity e, boolean loadTags) throws SQLException {
public void loadEntityData(Entity e) throws SQLException {
if (e.isDataLoaded()) { //data was already loaded, nothing to do
return;
}
if (e instanceof Node || (e instanceof Way && !((Way) e).getNodes().isEmpty())) {
// do not load tags for nodes inside way
return;
}
if(dialect == DBDialect.NOSQL){
loadEntityDataNoSQL(e, loadTags);
loadEntityDataNoSQL(e);
e.entityDataLoaded();
return;
}
@ -172,6 +188,9 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
way.putTag(rs.getString(3), rs.getString(4));
}
}
if (way.getNodes() == null) {
System.err.println("Strange, way with id:" + i.getId() + " has no nodes?");
}
rs.close();
}
} else if (i.getType() == EntityType.RELATION) {
@ -201,34 +220,32 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
}
e.initializeLinks(map);
e.entityDataLoaded();
}
public int iterateOverEntities(IProgress progress, EntityType type, OsmDbVisitor visitor) throws SQLException, InterruptedException {
if(dialect == DBDialect.NOSQL){
return iterateOverEntitiesNoSQL(progress, type, visitor);
}
Statement statement = dbConn.createStatement();
String select;
PreparedStatement select;
int count = 0;
// stat.executeUpdate("create table tags (id "+longType+", type smallint, skeys varchar(1024), value varchar(1024))");
// stat.executeUpdate("create table ways (id "+longType+", node "+longType+", ord smallint)");
// stat.executeUpdate("create table relations (id "+longType+", member "+longType+", type smallint, role varchar(1024), ord smallint)");
computeRealCounts(statement);
statement.close();
if (type == EntityType.NODE) {
// filter out all nodes without tags
select = "select n.id, n.latitude, n.longitude, t.skeys, t.value from node n inner join tags t on n.id = t.id and t.type = 0 order by n.id"; //$NON-NLS-1$
select = iterateNodes;
count = allNodes;
} else if (type == EntityType.WAY) {
select = "select w.id, w.node, w.ord, t.skeys, t.value, n.latitude, n.longitude " + //$NON-NLS-1$
"from ways w left join tags t on w.id = t.id and t.type = 1 and w.ord = 0 inner join node n on w.node = n.id " + //$NON-NLS-1$
"order by w.id, w.ord"; //$NON-NLS-1$
select = iterateWays;
count = allWays;
} else {
select = "select r.id, t.skeys, t.value from relations r inner join tags t on t.id = r.id and t.type = 2 and r.ord = 0"; //$NON-NLS-1$
select = iterateRelations;
count = allRelations;
}
progress.startWork(count);
@ -236,37 +253,34 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
BlockingQueue<Entity> toProcess = new ArrayBlockingQueue<Entity>(100000);
//produce
EntityProducer entityProducer = new EntityProducer(toProcess, type, statement, select);
EntityProducer entityProducer = new EntityProducer(toProcess, type, select);
entityProducer.start();
count = 0;
while (true) {
Entity entityToProcess = toProcess.take();
if (entityToProcess == entityProducer.getEndingEntity()) {
//the last entity...
break;
}
int counter = 0;
Entity entityToProcess = null;
Entity endEntity = entityProducer.getEndingEntity();
while ((entityToProcess = toProcess.take()) != endEntity) {
if (progress != null) {
progress.progress(1);
}
count++;
counter++;
visitor.iterateEntity(entityToProcess, this);
}
return count;
}
private void computeRealCounts(Statement statement) throws SQLException {
public void computeRealCounts(Statement statement) throws SQLException {
if (!realCounts) {
realCounts = true;
// filter out all nodes without tags
allNodes = statement.executeQuery("select count(*) from node n inner join tags t on n.id = t.id and t.type = 0").getInt(1); //$NON-NLS-1$
allWays = statement.executeQuery("select count(*) from ways w").getInt(1); //$NON-NLS-1$
allRelations = statement.executeQuery("select count(*) from relations r inner join tags t on t.id = r.id and t.type = 2 and r.ord = 0").getInt(1); //$NON-NLS-1$
allNodes = statement.executeQuery("select count(distinct n.id) from node n inner join tags t on n.id = t.id and t.type = 0").getInt(1); //$NON-NLS-1$
allWays = statement.executeQuery("select count(distinct w.id) from ways w").getInt(1); //$NON-NLS-1$
allRelations = statement.executeQuery("select count(distinct r.id) from relations r inner join tags t on t.id = r.id and t.type = 2 and r.ord = 0").getInt(1); //$NON-NLS-1$
}
}
private void loadEntityDataNoSQL(Entity e, boolean loadTags) {
private void loadEntityDataNoSQL(Entity e) {
Collection<EntityId> ids = e instanceof Relation ? ((Relation) e).getMemberIds() : ((Way) e).getEntityIds();
Map<EntityId, Entity> map = new LinkedHashMap<EntityId, Entity>();
for (EntityId i : ids) {
@ -275,7 +289,7 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
String value = accessor.get(randomAccessOptions, key);
if (value != null && value.length() > 0) {
try {
Entity es = loadEntityNoSqlFromValue(randomAccessOptions, key, value, loadTags, false);
Entity es = loadEntityNoSqlFromValue(randomAccessOptions, key, value, false);
map.put(i, es);
} catch (JSONException e1) {
log.warn(key + " - " + e1.getMessage() + " " + value + "("+value.length()+"]", e1);
@ -292,7 +306,7 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
}
private Entity loadEntityNoSqlFromValue(ReadOptions opts,
String key, String value, boolean loadTags, boolean skipIfEmptyTags) throws JSONException{
String key, String value, boolean skipIfEmptyTags) throws JSONException{
if(value == null){
return null;
}
@ -346,7 +360,7 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
while(n == ArraySerializer.ELEMENT){
String pointId = "0"+ tokenizer.value();
String pointVal = this.accessor.get(opts, pointId);
Node node = (Node) loadEntityNoSqlFromValue(opts, pointId, pointVal, false, false);
Node node = (Node) loadEntityNoSqlFromValue(opts, pointId, pointVal, false);
if(node != null){
((Way) e).addNode(node);
}
@ -398,11 +412,11 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
try {
Entity e = null;
if (type == EntityType.NODE) {
e = loadEntityNoSqlFromValue(opts, key, value, true, true);
e = loadEntityNoSqlFromValue(opts, key, value, true);
} else if (type == EntityType.WAY) {
e = loadEntityNoSqlFromValue(opts, key, value, true, false);
e = loadEntityNoSqlFromValue(opts, key, value, false);
} else {
e = loadEntityNoSqlFromValue(opts, key, value, true, false);
e = loadEntityNoSqlFromValue(opts, key, value, false);
}
if(e != null){
@ -435,6 +449,15 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
if (pselectTags != null) {
pselectTags.close();
}
if (iterateNodes != null) {
iterateNodes.close();
}
if (iterateRelations != null) {
iterateRelations.close();
}
if (iterateWays != null) {
iterateWays.close();
}
}
}
@ -442,17 +465,14 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
public class EntityProducer extends Thread {
private final BlockingQueue<Entity> toProcess;
private final Statement statement;
private final String select;
private final PreparedStatement select;
private final EntityType type;
private final Entity endingEntity = new Node(0,0,0);
public EntityProducer(BlockingQueue<Entity> toProcess, EntityType type,
Statement statement, String select) {
public EntityProducer(BlockingQueue<Entity> toProcess, EntityType type, PreparedStatement select2) {
this.toProcess = toProcess;
this.type = type;
this.statement = statement;
this.select = select;
this.select = select2;
setDaemon(true);
setName("EntityProducer");
}
@ -465,7 +485,8 @@ public class OsmDbAccessor implements OsmDbAccessorContext {
public void run() {
ResultSet rs;
try {
rs = statement.executeQuery(select);
select.execute();
rs = select.getResultSet();
// rs.setFetchSize(1000); !! not working for SQLite would case troubles probably
Entity prevEntity = null;

View file

@ -6,5 +6,5 @@ import net.osmand.osm.Entity;
public interface OsmDbAccessorContext {
public void loadEntityData(Entity e, boolean loadTags) throws SQLException;
public void loadEntityData(Entity e) throws SQLException;
}

View file

@ -2,8 +2,10 @@ package net.osmand.osm;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import net.osmand.osm.OSMSettings.OSMTagKey;
@ -98,6 +100,7 @@ public abstract class Entity {
// lazy initializing
private Map<String, String> tags = null;
private final long id;
private boolean dataLoaded;
public Entity(long id) {
this.id = id;
@ -190,5 +193,28 @@ public abstract class Entity {
}
return true;
}
public Set<String> getIsInNames() {
String values = getTag(OSMTagKey.IS_IN);
if (values == null) {
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;
}
}