implement user stories

git-svn-id: https://osmand.googlecode.com/svn/trunk@111 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-06-01 21:16:56 +00:00
parent fdcb7efefd
commit 7dd67ea397
16 changed files with 163 additions and 66 deletions

View file

@ -5,5 +5,6 @@
<classpathentry kind="lib" path="lib/bzip2-20090327.jar"/>
<classpathentry kind="lib" path="lib/sqlitejdbc-v056.jar"/>
<classpathentry kind="lib" path="lib/commons-logging-1.1.1.jar"/>
<classpathentry kind="lib" path="lib/icu4j-4_4_1.jar" sourcepath="C:/Download/icu4j-4_4_1-src.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

Binary file not shown.

View file

@ -81,4 +81,16 @@ public class Algoritms {
}
}
public static boolean removeAllFiles(File f){
if(f.isDirectory()){
boolean deleted = true;
for(File c : f.listFiles()){
deleted &= removeAllFiles(c);
}
return f.delete();
} else {
return f.delete();
}
}
}

View file

@ -11,52 +11,49 @@ public class ToDoConstants {
*/
public int DESCRIBE_ABOUT_AUTHORS = 8;
// TODO team :
// 1. write letters (UI/strings)
// TODO ANDROID
// TODO ANDROID in release 0.1
// 25. POI search near to map location (show categories & type). Second cut. (implement incremental search)
// 29. Show opened/closed amenities (in search poi).
// 13. Save point as favorite & introduce favorite points dialog
// 3. Revise osmand UI. Preparing new icons (revise UI 18, 2, ). Main application icon, back to location icon.
// 14. Show zoom level on map
// 24. Implement ResourceManager, load cities/streets/buildings on Low memory (clear previous all addresses cities).
// 25. Show opened/closed amenities.
// 27. Search intersection of streets.
// 26. Show the whole street on map (when it is chosen in search activity). Possibly extend that story to show layer with streets.
// 27. Search intersection of streets (+)
// NOT in release 0.1
// 8. Enable change POI directly on map (requires OSM login)
// 16. Support open street bugs api.
// 20. Implement save track/route to gpx (?)
// 26. Show the whole street on map (when it is chosen in search activity). Possibly extend that story to show layer with streets.
// 30. Performance issue : introduce one place where refreshMap will be called using postMessage mechanism (delay more than > 50 ? ms).
// FIXME Bugs Android :
// 1. When firstly run osmand navigation (from notification bar) show map & go to menu shows desktop.
// No chance to close application
// 6. Understand concept of application where to save/restore global setting.
// (for example reset navigate to point, reset link map with location). It should be reset after user call exit.
// Call ResourceManager.close when it is needed.
// 8. Introduce activity search by location (unify with existing dialog)
// 9. When all features will be ready we can remove show location from context menu
// 10. Notification is gone after clear all notifications
// Performance improvements Android :
// 1. Introducing one place where refreshMap will be called using postMessage mechanism (delay more than > 50 ? ms)
// 2. Introducing cache of file names that are on disk (creating new File() consumes a lot of memory)
// 2. Introducing cache of file names that are on disk (creating new File() consumes a lot of memory) (+)
// TODO SWING:
// 2. Configure file log & see log from file (add uncaught exception handling)
// 5. Implement suppress warning for duplicate id
// 6. Implement renaming/deleting street/building/city
// 8. Implement basic transliteration version
// 7. Implement saving bundle of tiles in different folder
// 9. Using Collator in all TreeSet/TreeMap/Comparators
// TODO SWING : in release 0.1
// 5. Implement suppress warning for duplicate id (+)
// 2. Configure file log & see log from file (add uncaught exception handling) (+)
// 6. Implement renaming/deleting street/building/city (+)
// 7. Implement saving bundle of tiles in different folder (+)
// NOT in release 0.1
// 1. Download tiles without using dir tiles
// DONE ANDROID :
// 24. Implement ResourceManager, load cities/streets/buildings on Low memory (clear previous all addresses cities).
// 28. Implement transliteration search for android version
// 5. Search for city/streets/buildings
// 15. Investigate interruption of any long running operation & implement where it is needed.
// ProgressDialogImplementation should support setOnCancelListener or obtain CANCEL message &
@ -72,5 +69,5 @@ public class ToDoConstants {
// 18. Implement go to point
// DONE SWING
// 8. Implement basic transliteration version
}

View file

@ -87,12 +87,13 @@ public class Amenity extends MapObject {
private String subType;
private AmenityType type;
private String openingHours;
public Amenity(Entity entity){
super(entity);
this.type = getType(entity);
this.subType = getSubType(entity);
this.openingHours = entity.getTag(OSMTagKey.OPENING_HOURS);
}
public Amenity(){
@ -153,19 +154,27 @@ public class Amenity extends MapObject {
return false;
}
public String getSimpleFormat(){
return Algoritms.capitalizeFirstLetterAndLowercase(getType().toString()) +
" : " + getSubType() + " " +getName();
public String getOpeningHours() {
return openingHours;
}
public String getStringWithoutType(){
return getSubType() + " " +getName();
public void setOpeningHours(String openingHours) {
this.openingHours = openingHours;
}
public String getSimpleFormat(boolean en){
return Algoritms.capitalizeFirstLetterAndLowercase(getType().toString()) +
" : " + getSubType() + " " +getName(en);
}
public String getStringWithoutType(boolean en){
return getSubType() + " " +getName(en);
}
@Override
public String toString() {
return getSimpleFormat();
return getSimpleFormat(false);
}

View file

@ -1,5 +1,6 @@
package com.osmand.data;
import java.text.Collator;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
@ -44,7 +45,7 @@ public class City extends MapObject {
private CityType type = null;
// Be attentive ! Working with street names ignoring case
private Map<String, Street> streets = new TreeMap<String, Street>();
private Map<String, Street> streets = new TreeMap<String, Street>(Collator.getInstance());
public City(Node el){
super(el);
@ -74,8 +75,9 @@ public class City extends MapObject {
streets.clear();
}
public Street registerStreet(Street street){
String name = street.getName().toLowerCase();
public Street registerStreet(Street street, boolean en){
String name = en ? street.getEnName(): street.getName();
name = name.toLowerCase();
if(!Algoritms.isEmpty(name)){
if(!streets.containsKey(name)){
return streets.put(name, street);
@ -90,6 +92,10 @@ public class City extends MapObject {
return null;
}
public Street registerStreet(Street street){
return registerStreet(street, false);
}
public Street registerBuilding(Entity e){
String number = e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER);
String street = e.getTag(OSMTagKey.ADDR_STREET);

View file

@ -1,5 +1,7 @@
package com.osmand.data;
import java.text.Collator;
import com.osmand.osm.Entity;
import com.osmand.osm.LatLon;
import com.osmand.osm.MapUtils;
@ -8,6 +10,7 @@ import com.osmand.osm.OSMSettings.OSMTagKey;
public abstract class MapObject implements Comparable<MapObject> {
protected String name = null;
protected String enName = null;
protected LatLon location = null;
protected Long id = null;
@ -39,6 +42,14 @@ public abstract class MapObject implements Comparable<MapObject> {
return null;
}
public String getName(boolean en){
if(en){
return getEnName();
} else {
return getName();
}
}
public String getName() {
if (this.name != null) {
return this.name;
@ -54,6 +65,14 @@ public abstract class MapObject implements Comparable<MapObject> {
this.name = name;
}
public String getEnName() {
return enName;
}
public void setEnName(String enName) {
this.enName = enName;
}
public LatLon getLocation(){
return location;
}
@ -64,7 +83,7 @@ public abstract class MapObject implements Comparable<MapObject> {
@Override
public int compareTo(MapObject o) {
return getName().compareTo(o.getName());
return Collator.getInstance().compare(getName(), o.getName());
}
public void doDataPreparation() {

View file

@ -1,5 +1,6 @@
package com.osmand.data;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -27,10 +28,19 @@ public class Region extends MapObject {
}
}
private static class CityComparator implements Comparator<City>{
public static class CityComparator implements Comparator<City>{
private final boolean en;
public CityComparator(boolean en){
this.en = en;
}
Collator collator = Collator.getInstance();
@Override
public int compare(City o1, City o2) {
return o1.getName().compareTo(o2.getName());
if(en){
return collator.compare(o1.getEnName(), o2.getEnName());
} else {
return collator.compare(o1.getName(), o2.getName());
}
}
}
@ -139,7 +149,7 @@ public class Region extends MapObject {
public void doDataPreparation(){
CityComparator comp = new CityComparator();
CityComparator comp = new CityComparator(false);
for(CityType t : cities.keySet()){
Collections.sort(cities.get(t), comp);
for(City c : cities.get(t)){

View file

@ -41,6 +41,7 @@ public class DataIndexReader {
while(set.next()){
City city = new City(CityType.valueFromString(set.getString(IndexCityTable.CITY_TYPE.ordinal() + 1)));
city.setName(set.getString(IndexCityTable.NAME.ordinal() + 1));
city.setEnName(set.getString(IndexCityTable.NAME_EN.ordinal() + 1));
city.setLocation(set.getDouble(IndexCityTable.LATITUDE.ordinal() + 1),
set.getDouble(IndexCityTable.LONGITUDE.ordinal() + 1));
city.setId(set.getLong(IndexCityTable.ID.ordinal() + 1));
@ -60,6 +61,7 @@ public class DataIndexReader {
while(set.next()){
Street street = new Street(city);
street.setName(set.getString(IndexStreetTable.NAME.ordinal() + 1));
street.setEnName(set.getString(IndexStreetTable.NAME_EN.ordinal() + 1));
street.setLocation(set.getDouble(IndexStreetTable.LATITUDE.ordinal() + 1),
set.getDouble(IndexStreetTable.LONGITUDE.ordinal() + 1));
street.setId(set.getLong(IndexStreetTable.ID.ordinal() + 1));
@ -78,6 +80,7 @@ public class DataIndexReader {
while(set.next()){
Building building = new Building();
building.setName(set.getString(IndexBuildingTable.NAME.ordinal() + 1));
building.setEnName(set.getString(IndexBuildingTable.NAME_EN.ordinal() + 1));
building.setLocation(set.getDouble(IndexBuildingTable.LATITUDE.ordinal() + 1),
set.getDouble(IndexBuildingTable.LONGITUDE.ordinal() + 1));
building.setId(set.getLong(IndexBuildingTable.ID.ordinal() + 1));

View file

@ -67,22 +67,24 @@ public class DataIndexWriter {
Connection conn = DriverManager.getConnection("jdbc:sqlite:"+file.getAbsolutePath());
try {
Statement stat = conn.createStatement();
assert IndexPoiTable.values().length == 6;
assert IndexPoiTable.values().length == 8;
stat.executeUpdate(IndexConstants.generateCreateSQL(IndexPoiTable.values()));
stat.executeUpdate(IndexConstants.generateCreateIndexSQL(IndexPoiTable.values()));
stat.close();
PreparedStatement prep = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexPoiTable.getTable(), 6));
IndexConstants.generatePrepareStatementToInsert(IndexPoiTable.getTable(), 8));
conn.setAutoCommit(false);
int currentCount = 0;
for (Amenity a : region.getAmenityManager().getAllObjects()) {
prep.setLong(IndexPoiTable.ID.ordinal() + 1, a.getId());
prep.setDouble(IndexPoiTable.LATITUDE.ordinal() + 1, a.getLocation().getLatitude());
prep.setDouble(IndexPoiTable.LONGITUDE.ordinal() + 1, a.getLocation().getLongitude());
prep.setString(IndexPoiTable.NAME_EN.ordinal() + 1, a.getEnName());
prep.setString(IndexPoiTable.NAME.ordinal() + 1, a.getName());
prep.setString(IndexPoiTable.TYPE.ordinal() + 1, AmenityType.valueToString(a.getType()));
prep.setString(IndexPoiTable.SUBTYPE.ordinal() + 1, a.getSubType());
prep.setString(IndexPoiTable.OPENING_HOURS.ordinal() + 1 , a.getOpeningHours());
prep.addBatch();
currentCount++;
if(currentCount >= BATCH_SIZE){
@ -114,10 +116,10 @@ public class DataIndexWriter {
Connection conn = DriverManager.getConnection("jdbc:sqlite:"+file.getAbsolutePath());
try {
Statement stat = conn.createStatement();
assert IndexCityTable.values().length == 5;
assert IndexBuildingTable.values().length == 5;
assert IndexCityTable.values().length == 6;
assert IndexBuildingTable.values().length == 6;
assert IndexStreetNodeTable.values().length == 5;
assert IndexStreetTable.values().length == 5;
assert IndexStreetTable.values().length == 6;
stat.executeUpdate(IndexConstants.generateCreateSQL(IndexCityTable.values()));
stat.executeUpdate(IndexConstants.generateCreateIndexSQL(IndexCityTable.values()));
@ -130,11 +132,11 @@ public class DataIndexWriter {
stat.close();
PreparedStatement prepCity = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexCityTable.getTable(), 5));
IndexConstants.generatePrepareStatementToInsert(IndexCityTable.getTable(), 6));
PreparedStatement prepStreet = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexStreetTable.getTable(), 5));
IndexConstants.generatePrepareStatementToInsert(IndexStreetTable.getTable(), 6));
PreparedStatement prepBuilding = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexBuildingTable.getTable(), 5));
IndexConstants.generatePrepareStatementToInsert(IndexBuildingTable.getTable(), 6));
PreparedStatement prepStreetNode = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexStreetNodeTable.getTable(), 5));
Map<PreparedStatement, Integer> count = new HashMap<PreparedStatement, Integer>();
@ -153,6 +155,7 @@ public class DataIndexWriter {
prepCity.setDouble(IndexCityTable.LATITUDE.ordinal() + 1, city.getLocation().getLatitude());
prepCity.setDouble(IndexCityTable.LONGITUDE.ordinal() + 1, city.getLocation().getLongitude());
prepCity.setString(IndexCityTable.NAME.ordinal() + 1, city.getName());
prepCity.setString(IndexCityTable.NAME_EN.ordinal() + 1, city.getEnName());
prepCity.setString(IndexCityTable.CITY_TYPE.ordinal() + 1, CityType.valueToString(city.getType()));
addBatch(count, prepCity);
@ -161,6 +164,7 @@ public class DataIndexWriter {
continue;
}
prepStreet.setLong(IndexStreetTable.ID.ordinal() + 1, street.getId());
prepStreet.setString(IndexStreetTable.NAME_EN.ordinal() + 1, street.getEnName());
prepStreet.setDouble(IndexStreetTable.LATITUDE.ordinal() + 1, street.getLocation().getLatitude());
prepStreet.setDouble(IndexStreetTable.LONGITUDE.ordinal() + 1, street.getLocation().getLongitude());
prepStreet.setString(IndexStreetTable.NAME.ordinal() + 1, street.getName());
@ -189,6 +193,7 @@ public class DataIndexWriter {
prepBuilding.setDouble(IndexBuildingTable.LATITUDE.ordinal() + 1, building.getLocation().getLatitude());
prepBuilding.setDouble(IndexBuildingTable.LONGITUDE.ordinal() + 1, building.getLocation().getLongitude());
prepBuilding.setString(IndexBuildingTable.NAME.ordinal() + 1, building.getName());
prepBuilding.setString(IndexBuildingTable.NAME_EN.ordinal() + 1, building.getEnName());
prepBuilding.setLong(IndexBuildingTable.STREET.ordinal() + 1, street.getId());
addBatch(count, prepBuilding);
}

View file

@ -105,7 +105,7 @@ public class IndexConstants {
public enum IndexPoiTable implements IndexColumn {
ID("long"), LATITUDE("double", true), LONGITUDE("double", true), NAME, TYPE, SUBTYPE;
ID("long"), LATITUDE("double", true), LONGITUDE("double", true), OPENING_HOURS, NAME, NAME_EN, TYPE, SUBTYPE;
boolean index = false;
String type = null;
private IndexPoiTable(){}
@ -135,7 +135,7 @@ public class IndexConstants {
public enum IndexCityTable implements IndexColumn {
ID("long"), LATITUDE("double", true), LONGITUDE("double", true), NAME, CITY_TYPE;
ID("long"), LATITUDE("double", true), LONGITUDE("double", true), NAME, NAME_EN, CITY_TYPE;
boolean index = false;
String type = null;
@ -171,7 +171,7 @@ public class IndexConstants {
}
public enum IndexStreetTable implements IndexColumn {
ID("long"), LATITUDE("double", true), LONGITUDE("double", true), NAME, CITY("long", true);
ID("long"), LATITUDE("double", true), LONGITUDE("double", true), NAME, NAME_EN, CITY("long", true);
boolean index = false;
String type = null;
@ -243,7 +243,7 @@ public class IndexConstants {
}
public enum IndexBuildingTable implements IndexColumn {
ID("long"), LATITUDE("double"), LONGITUDE("double"), NAME, STREET("long", true);
ID("long"), LATITUDE("double"), LONGITUDE("double"), NAME, NAME_EN, STREET("long", true);
boolean index = false;
String type = null;

View file

@ -19,11 +19,14 @@ import org.apache.commons.logging.LogFactory;
import org.apache.tools.bzip2.CBZip2InputStream;
import org.xml.sax.SAXException;
import com.ibm.icu.text.Transliterator;
import com.osmand.Algoritms;
import com.osmand.IProgress;
import com.osmand.data.Amenity;
import com.osmand.data.Building;
import com.osmand.data.City;
import com.osmand.data.DataTileManager;
import com.osmand.data.MapObject;
import com.osmand.data.Region;
import com.osmand.data.Street;
import com.osmand.data.City.CityType;
@ -169,6 +172,7 @@ public class DataExtraction {
if (conn != null) {
try {
conn.close();
new File(workingDir, NODES_DB).delete();
} catch (SQLException e) {
}
}
@ -301,9 +305,35 @@ public class DataExtraction {
}
// 7. Call data preparation to sort cities, calculate center location, assign id to objects
country.doDataPreparation();
// 8. Transliterate names to english
Transliterator latin = Transliterator.getInstance("Any-Latin;NFD;[:Nonspacing Mark:] Remove;NFC");
if(latin != null){
convertEnglishName(country, latin);
for(CityType c : CityType.values() ){
for(City city : country.getCitiesByType(c)){
convertEnglishName(city, latin);
for(Street s : city.getStreets()){
convertEnglishName(s, latin);
for(Building b : s.getBuildings()){
convertEnglishName(b, latin);
}
}
}
}
for(Amenity a : country.getAmenityManager().getAllObjects()){
convertEnglishName(a, latin);
}
}
return country;
}
private void convertEnglishName(MapObject o, Transliterator transliterator){
String name = o.getName();
if(name != null){
o.setEnName(transliterator.transliterate(name));
}
}
private void readingBuildings(IProgress progress, final ArrayList<Entity> buildings, Region country) {
// found buildings (index addresses)

View file

@ -18,6 +18,7 @@ public class OSMSettings {
SHOP("shop"),
LEISURE("leisure"),
TOURISM("tourism"),
OPENING_HOURS("opening_hours"),
;
private final String value;

View file

@ -221,12 +221,6 @@ public class OsmBaseStorage extends DefaultHandler {
}
public Map<Long, Entity> getRegisteredEntities() {
return entities;
}

View file

@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Stack;
@ -29,6 +30,7 @@ import java.util.Map.Entry;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import com.ibm.icu.text.Transliterator;
import com.osmand.Algoritms;
import com.osmand.data.MapObject;
import com.osmand.osm.Entity;
@ -169,4 +171,14 @@ public class OsmStorageWriter {
writer.writeEndElement();
}
}
public static void main(String[] args) {
Transliterator inst = Transliterator.getInstance("Any-Latin;NFD;[:Nonspacing Mark:] Remove;NFC");
Enumeration<String> e = Transliterator.getAvailableIDs();
while(e.hasMoreElements()){
System.out.println(e.nextElement());
}
System.out.println(inst.transliterate("Привет всемь жаваыфайу ы х й к ще цуккак у ваа"));
}
}

View file

@ -18,9 +18,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.AbstractAction;
import javax.swing.DefaultListCellRenderer;
@ -73,9 +73,7 @@ import com.osmand.data.Region;
import com.osmand.data.Street;
import com.osmand.data.Amenity.AmenityType;
import com.osmand.data.City.CityType;
import com.osmand.data.index.DataIndexReader;
import com.osmand.data.index.DataIndexWriter;
import com.osmand.data.index.IndexConstants;
import com.osmand.data.preparation.DataExtraction;
import com.osmand.map.IMapLocationListener;
import com.osmand.osm.Entity;
@ -369,9 +367,9 @@ public class OsmExtractionUI implements IMapLocationListener {
builder.writeAddress();
msg.append(", Address index ").append("successfully created");
}
new DataIndexReader().testIndex(new File(
DataExtractionSettings.getSettings().getDefaultWorkingDir(),
IndexConstants.ADDRESS_INDEX_DIR+region.getName()+IndexConstants.ADDRESS_INDEX_EXT));
// new DataIndexReader().testIndex(new File(
// DataExtractionSettings.getSettings().getDefaultWorkingDir(),
// IndexConstants.ADDRESS_INDEX_DIR+region.getName()+IndexConstants.ADDRESS_INDEX_EXT));
msg.append(".");
JOptionPane pane = new JOptionPane(msg);
JDialog dialog = pane.createDialog(frame, "Generation data");
@ -703,7 +701,7 @@ public class OsmExtractionUI implements IMapLocationListener {
MapUtils.sortListOfMapObject(closestAmenities, newLatitude, newLongitude);
Map<AmenityType, List<Amenity>> filter = new TreeMap<AmenityType, List<Amenity>>();
Map<AmenityType, List<Amenity>> filter = new HashMap<AmenityType, List<Amenity>>();
for (Amenity n : closestAmenities) {
AmenityType type = n.getType();
if (!filter.containsKey(type)) {
@ -719,7 +717,7 @@ public class OsmExtractionUI implements IMapLocationListener {
if (filter.get(type) != null) {
for (Amenity n : filter.get(type)) {
int dist = (int) (MapUtils.getDistance(n.getLocation(), newLatitude, newLongitude));
String str = n.getStringWithoutType() + " [" + dist + " m ]";
String str = n.getStringWithoutType(false) + " [" + dist + " m ]";
DataExtractionTreeNode node = new DataExtractionTreeNode(str, n);
((DefaultMutableTreeNode) amenitiesTree.getChildAt(i)).add(node);
}
@ -731,7 +729,7 @@ public class OsmExtractionUI implements IMapLocationListener {
for (int i = 0; i < 15 && i < closestAmenities.size(); i++) {
Amenity n = closestAmenities.get(i);
int dist = (int) (MapUtils.getDistance(n.getLocation(), newLatitude, newLongitude));
String str = n.getSimpleFormat() + " [" + dist + " m ]";
String str = n.getSimpleFormat(false) + " [" + dist + " m ]";
((DefaultMutableTreeNode) amenitiesTree.getChildAt(0)).add(new DataExtractionTreeNode(str, n));
((DefaultTreeModel)treePlaces.getModel()).nodeStructureChanged(amenitiesTree.getChildAt(0));
}