1 package tim.prune.function;
3 import java.io.InputStream;
4 import java.io.UnsupportedEncodingException;
6 import java.net.URLEncoder;
7 import java.util.ArrayList;
9 import javax.swing.JOptionPane;
10 import javax.xml.parsers.SAXParser;
11 import javax.xml.parsers.SAXParserFactory;
14 import tim.prune.I18nManager;
15 import tim.prune.data.DataPoint;
16 import tim.prune.data.Field;
17 import tim.prune.data.Latitude;
18 import tim.prune.data.Longitude;
19 import tim.prune.function.search.GenericDownloaderFunction;
20 import tim.prune.function.search.SearchResult;
23 * Function to search Wikipedia for place names
25 public class SearchWikipediaNames extends GenericDownloaderFunction
28 private String _searchTerm = null;
29 /** Maximum number of results to get */
30 private static final int MAX_RESULTS = 20;
31 /** Username to use for geonames queries */
32 private static final String GEONAMES_USERNAME = "gpsprune";
36 * @param inApp App object
38 public SearchWikipediaNames(App inApp) {
45 public String getNameKey() {
46 return "function.searchwikipedianames";
50 * @param inColNum index of column, 0 or 1
51 * @return key for this column
53 protected String getColumnKey(int inColNum)
55 if (inColNum == 0) return "dialog.wikipedia.column.name";
60 * Before dialog is shown, need to get search term
64 Object search = JOptionPane.showInputDialog(_app.getFrame(),
65 I18nManager.getText("dialog.searchwikipedianames.search"),
66 I18nManager.getText(getNameKey()),
67 JOptionPane.QUESTION_MESSAGE, null, null, "");
70 _searchTerm = search.toString().toLowerCase();
71 if (!_searchTerm.equals("")) {
78 * Run method to call geonames in separate thread
82 _statusLabel.setText(I18nManager.getText("confirm.running"));
84 // Replace awkward characters with character equivalents
85 final String searchTerm = encodeSearchTerm(_searchTerm);
87 // Firstly try the local language
88 String lang = I18nManager.getText("wikipedia.lang");
89 submitSearch(searchTerm, lang);
90 // If we didn't get anything, try a secondary language
91 if (_trackListModel.isEmpty() && _errorMessage == null && lang.equals("als")) {
92 submitSearch(searchTerm, "de");
94 // If still nothing then try english
95 if (_trackListModel.isEmpty() && _errorMessage == null && !lang.equals("en")) {
96 submitSearch(searchTerm, "en");
99 // Set status label according to error or "none found", leave blank if ok
100 if (_errorMessage == null && _trackListModel.isEmpty()) {
101 _errorMessage = I18nManager.getText("dialog.wikipedia.nonefound");
103 _statusLabel.setText(_errorMessage == null ? "" : _errorMessage);
107 * Submit the given search to the server
108 * @param inSearchTerm search term
109 * @param inLang language code such as en, de
111 private void submitSearch(String inSearchTerm, String inLang)
113 // System.out.println("Searching for '" + inSearchTerm + "' with lang: " + inLang);
115 String urlString = "http://api.geonames.org/wikipediaSearch?title=" + inSearchTerm
116 + "&maxRows=" + MAX_RESULTS + "&lang=" + inLang + "&username=" + GEONAMES_USERNAME;
117 // Parse the returned XML with a special handler
118 GetWikipediaXmlHandler xmlHandler = new GetWikipediaXmlHandler();
119 InputStream inStream = null;
123 URL url = new URL(urlString);
124 SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
125 inStream = url.openStream();
126 saxParser.parse(inStream, xmlHandler);
128 catch (Exception e) {
129 _errorMessage = e.getClass().getName() + " - " + e.getMessage();
131 // Close stream and ignore errors
134 } catch (Exception e) {}
135 // Add track list to model
136 ArrayList<SearchResult> trackList = xmlHandler.getTrackList();
137 // TODO: Do a better job of sorting replies by relevance - use three different lists
138 _trackListModel.addTracks(trackList);
142 * Replace tricky characters in the search term and encode the others
143 * @param inSearchTerm entered search term
144 * @return modified search term to give to geonames
146 private static final String encodeSearchTerm(String inSearchTerm)
148 if (inSearchTerm != null && inSearchTerm.length() > 0)
150 // Replace umlauts oe, ue, ae, OE, UE, AE, szlig
151 StringBuilder sb = new StringBuilder();
152 final int numChars = inSearchTerm.length();
153 for (int i=0; i<numChars; i++)
155 char c = inSearchTerm.charAt(i);
158 // German umlauted vowels, add an "e"
159 case '\u00fc' : sb.append("ue"); break;
160 case '\u00e4' : sb.append("ae"); break;
161 case '\u00f6' : sb.append("oe"); break;
163 case '\u00df' : sb.append("ss"); break;
165 case '\u00e8' : case '\u00e9' :
166 case '\u00ea' : case '\u00eb' : sb.append('e'); break;
167 case '\u00e0' : case '\u00e1' :
168 case '\u00e2' : sb.append('a'); break;
169 case '\u00f2' : case '\u00f3' :
170 case '\u00f4' : sb.append('o'); break;
171 case '\u00ec' : case '\u00ed' :
172 case '\u00ee' : case '\u00ef' : sb.append('i'); break;
173 // cedillas, ny, l bar
174 case '\u00e7' : sb.append('c'); break;
175 case '\u015f' : sb.append('s'); break;
176 case '\u00f1' : sb.append('n'); break;
177 case '\u0142' : sb.append('l'); break;
179 default : sb.append(c);
182 String searchTerm = inSearchTerm;
184 searchTerm = URLEncoder.encode(sb.toString(), "UTF-8");
185 } catch (UnsupportedEncodingException e1) {}
186 // System.out.println("Converted '" + inSearchTerm + "' to '" + searchTerm + "'");
193 * Load the selected point(s)
195 protected void loadSelected()
197 // Find the rows selected in the table and get the corresponding coords
198 int numSelected = _trackTable.getSelectedRowCount();
199 if (numSelected < 1) return;
200 int[] rowNums = _trackTable.getSelectedRows();
201 for (int i=0; i<numSelected; i++)
203 int rowNum = rowNums[i];
204 if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
206 String lat = _trackListModel.getTrack(rowNum).getLatitude();
207 String lon = _trackListModel.getTrack(rowNum).getLongitude();
208 if (lat != null && lon != null)
210 DataPoint point = new DataPoint(new Latitude(lat), new Longitude(lon), null);
211 point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false);
212 _app.createPoint(point);