countryCodes) {
130 | this.countryCodes = countryCodes;
131 | }
132 |
133 | /**
134 | * @return the countryBias
135 | */
136 | public String getCountryBias() {
137 | return countryBias;
138 | }
139 |
140 | /**
141 | * @param countryBias
142 | * the countryBias to set
143 | */
144 | public void setCountryBias(String countryBias) {
145 | this.countryBias = countryBias;
146 | }
147 |
148 | /**
149 | * @return the continentCode
150 | */
151 | public String getContinentCode() {
152 | return continentCode;
153 | }
154 |
155 | /**
156 | * @param continentCode
157 | * the continentCode to set
158 | */
159 | public void setContinentCode(String continentCode) {
160 | this.continentCode = continentCode;
161 | }
162 |
163 | /**
164 | * @return Returns the nameEquals.
165 | */
166 | public String getNameEquals() {
167 | return nameEquals;
168 | }
169 |
170 | /**
171 | * @param nameEquals
172 | * The nameEquals to set.
173 | */
174 | public void setNameEquals(String exactName) {
175 | this.nameEquals = exactName;
176 | }
177 |
178 | /**
179 | * @return Returns the featureCodes.
180 | */
181 | public String[] getFeatureCodes() {
182 | return featureCodes;
183 | }
184 |
185 | /**
186 | * @param featureCodes
187 | * The featureCodes to set.
188 | */
189 | public void setFeatureCodes(String[] featureCodes) {
190 | this.featureCodes = featureCodes;
191 | }
192 |
193 | public void setFeatureCode(String featureCode) {
194 | this.featureCodes = new String[] { featureCode };
195 | }
196 |
197 | /**
198 | * @return Returns the language.
199 | */
200 | public String getLanguage() {
201 | return language;
202 | }
203 |
204 | /**
205 | * @param language
206 | * The language to set.
207 | */
208 | public void setLanguage(String language) {
209 | this.language = language;
210 | }
211 |
212 | /**
213 | * @return Returns the maxRows.
214 | */
215 | public int getMaxRows() {
216 | return maxRows;
217 | }
218 |
219 | /**
220 | * @param maxRows
221 | * The maxRows to set.
222 | */
223 | public void setMaxRows(int maxRows) {
224 | this.maxRows = maxRows;
225 | }
226 |
227 | /**
228 | * @return Returns the name.
229 | */
230 | public String getName() {
231 | return name;
232 | }
233 |
234 | /**
235 | * search over the name field only.
236 | *
237 | * @param name
238 | * The name to set.
239 | */
240 | public void setName(String name) {
241 | this.name = name;
242 | }
243 |
244 | /**
245 | * @return Returns the q.
246 | */
247 | public String getQ() {
248 | return q;
249 | }
250 |
251 | /**
252 | * The main search term. The search is executed over all fields (place name,
253 | * country name, admin names, etc)
254 | *
255 | * @param q
256 | * The q to set.
257 | */
258 | public void setQ(String q) {
259 | this.q = q;
260 | }
261 |
262 | /**
263 | * @return Returns the startRow.
264 | */
265 | public int getStartRow() {
266 | return startRow;
267 | }
268 |
269 | /**
270 | * @param startRow
271 | * The startRow to set.
272 | */
273 | public void setStartRow(int startRow) {
274 | this.startRow = startRow;
275 | }
276 |
277 | /**
278 | * @return Returns the style.
279 | */
280 | public Style getStyle() {
281 | return style;
282 | }
283 |
284 | /**
285 | * @param style
286 | * The style to set.
287 | */
288 | public void setStyle(Style style) {
289 | this.style = style;
290 | }
291 |
292 | /**
293 | * @return Returns the tag.
294 | */
295 | public String getTag() {
296 | return tag;
297 | }
298 |
299 | /**
300 | * @param tag
301 | * The tag to set.
302 | */
303 | public void setTag(String tag) {
304 | this.tag = tag;
305 | }
306 |
307 | /**
308 | * @return Returns the nameStartsWith.
309 | */
310 | public String getNameStartsWith() {
311 | return nameStartsWith;
312 | }
313 |
314 | /**
315 | * @param nameStartsWith
316 | * The nameStartsWith to set.
317 | */
318 | public void setNameStartsWith(String nameStartsWith) {
319 | this.nameStartsWith = nameStartsWith;
320 | }
321 |
322 | /**
323 | * @return the featureClass
324 | */
325 | public FeatureClass getFeatureClass() {
326 | return featureClass;
327 | }
328 |
329 | /**
330 | * @param featureClass
331 | * the featureClass to set
332 | */
333 | public void setFeatureClass(FeatureClass featureClass) {
334 | this.featureClass = featureClass;
335 | }
336 |
337 | /**
338 | * @return the adminCode1
339 | */
340 | public String getAdminCode1() {
341 | return adminCode1;
342 | }
343 |
344 | /**
345 | * @param adminCode1
346 | * the adminCode1 to set
347 | */
348 | public void setAdminCode1(String adminCode1) {
349 | this.adminCode1 = adminCode1;
350 | }
351 |
352 | /**
353 | * @return the adminCode2
354 | */
355 | public String getAdminCode2() {
356 | return adminCode2;
357 | }
358 |
359 | /**
360 | * @param adminCode2
361 | * the adminCode2 to set
362 | */
363 | public void setAdminCode2(String adminCode2) {
364 | this.adminCode2 = adminCode2;
365 | }
366 |
367 | /**
368 | * @return the adminCode3
369 | */
370 | public String getAdminCode3() {
371 | return adminCode3;
372 | }
373 |
374 | /**
375 | * @param adminCode3
376 | * the adminCode3 to set
377 | */
378 | public void setAdminCode3(String adminCode3) {
379 | this.adminCode3 = adminCode3;
380 | }
381 |
382 | public String getAdminCode4() {
383 | return adminCode4;
384 | }
385 |
386 | public void setAdminCode4(String adminCode4) {
387 | this.adminCode4 = adminCode4;
388 | }
389 |
390 | /**
391 | * @return the fuzzy
392 | */
393 | public double getFuzzy() {
394 | return fuzzy;
395 | }
396 |
397 | /**
398 | * @param fuzzy the fuzzy to set
399 | */
400 | public void setFuzzy(double fuzzy) {
401 | this.fuzzy = fuzzy;
402 | }
403 |
404 | /**
405 | * @return the boundingBox
406 | */
407 | public BoundingBox getBoundingBox() {
408 | return boundingBox;
409 | }
410 |
411 | /**
412 | * @param boundingBox
413 | * the boundingBox to set
414 | */
415 | public void setBoundingBox(BoundingBox boundingBox) {
416 | this.boundingBox = boundingBox;
417 | }
418 |
419 | }
420 |
--------------------------------------------------------------------------------
/org/geonames/wikipedia/TextSummaryExtractor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007 Marc Wick, geonames.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package org.geonames.wikipedia;
18 |
19 | /**
20 | * @author marc
21 | *
22 | */
23 | public class TextSummaryExtractor {
24 |
25 | /**
26 | * extract a text summary from a wikipedia article. The wikipedia markup is
27 | * removed. The length of the summary is equal or lower the length of the
28 | * parameter. The extractor tries to end the summary at a fullstop. It stops
29 | * at a new paragraph.
30 | *
31 | * @param pText
32 | * @param length
33 | * @return
34 | */
35 | public static String extractSummary(String pText, int length) {
36 | return extractSummary(pText, length, true);
37 | }
38 |
39 | public static String extractSummary(String pText, int length,
40 | boolean stopAtParagraph) {
41 | if (pText == null) {
42 | return null;
43 | }
44 |
45 | String textCopy = new String(pText);
46 |
47 | // remove all wikipedia markup (paragraphs are kept)
48 | //
49 | StringBuilder summary = new StringBuilder();
50 | int idx = 0;
51 |
52 | // loop over all characters in input string
53 | while (idx > -1 && (summary.length() < 50 + 2 * length || length == 0)
54 | && idx < textCopy.length()) {
55 | // get next chacter
56 | char c = textCopy.charAt(idx);
57 |
58 | if (c == '{') {
59 | // skip template and set idx to end of template
60 | int endidx = skipTemplate(textCopy, idx);
61 | // do we have an audio template?
62 | if (textCopy.toLowerCase().indexOf("{{audio") == idx) {
63 | int begLabelIdx = textCopy.lastIndexOf("|", endidx);
64 | if (begLabelIdx > -1) {
65 | String label = textCopy.substring(begLabelIdx + 1,
66 | endidx - 2).trim();
67 | summary.append(label);
68 | }
69 | }
70 | if (textCopy.toLowerCase().indexOf("{{formatnum") == idx) {
71 | int begLabelIdx = textCopy.indexOf(":", idx);
72 | if (begLabelIdx > -1) {
73 |
74 | int endLabelIdx = endidx - 2;
75 | if (textCopy.indexOf("|", begLabelIdx) > -1) {
76 | endLabelIdx = textCopy.indexOf("|", begLabelIdx);
77 | }
78 |
79 | String label = textCopy.substring(begLabelIdx + 1,
80 | endLabelIdx).trim();
81 | summary.append(label);
82 | }
83 | }
84 | // skip template and set idx to end of template
85 | idx = endidx;
86 | continue;
87 | } else if (c == '<') {
88 | // is it a html comment
89 | if (textCopy.length() > idx + 1 && textCopy.charAt(idx + 1) == '!') {
90 | // skip html comment
91 | idx = skipHTMLComment(textCopy, idx);
92 | continue;
93 | } else {
94 | // html element starts here, skip it, set idx to end of html
95 | // element
96 | idx = skipHTMLElement(textCopy, idx);
97 | continue;
98 | }
99 | } else if (c == '[') {
100 |
101 | // look ahead to see whether we have a link
102 | if (textCopy.charAt(idx + 1) == '[') {
103 | // we have two square brackets "[[" (link)
104 |
105 | // get the end of the double square bracket
106 | int endOfLink = textCopy.indexOf("]]", idx);
107 |
108 | // image link ?
109 | int colon = textCopy.indexOf(":", idx);
110 | if (colon > -1 && colon < endOfLink) {
111 | // image link contains a caption which might contain
112 | // a link within the link
113 | idx = findEndOfLink(textCopy, idx);
114 | continue;
115 | }
116 |
117 | int beginAnchor = textCopy.indexOf("|", idx);
118 | if (beginAnchor > -1 && beginAnchor < endOfLink) {
119 | idx = beginAnchor + 1;
120 | } else {
121 | idx = idx + 2;
122 | }
123 | continue;
124 | } else {
125 | // next character is not a square brackets and thus a
126 | // reference link to be removed
127 | // get the end of the square bracket
128 | int endOfLink = textCopy.indexOf("]", idx);
129 | if (endOfLink > -1) {
130 | idx = endOfLink + 1;
131 | continue;
132 | }
133 | }
134 | } else if (c == ']') {
135 | // look ahead
136 | if (idx + 1 < textCopy.length() && textCopy.charAt(idx + 1) == ']') {
137 | idx = idx + 2;
138 | continue;
139 | }
140 | } else if (c == '=') {
141 | // look ahead
142 | if (idx + 1 < textCopy.length() && textCopy.charAt(idx + 1) == '=') {
143 | int endHeaderIdx = textCopy.indexOf("==", idx + 2);
144 | if (endHeaderIdx > -1) {
145 | idx = endHeaderIdx + 2;
146 | }
147 | continue;
148 | }
149 | }
150 |
151 | summary.append(c);
152 | idx++;
153 | }
154 |
155 | String textString = removeIndentAtBeginning(summary.toString());
156 | // remove empty parenthesis
157 | textString = textString.replaceAll("\\([^\\w]*\\)", "");
158 | // remove comma in front of parenthesis
159 | textString = textString.replaceAll("\\([, ]*", "(");
160 | textString = textString.replaceAll("[, ]*\\)", ")");
161 |
162 | textString = removeWhiteSpace(
163 | textString.replaceAll("\r", " ").replaceAll("\n", " ")
164 | .replaceAll("\t", " ")).trim();
165 |
166 | textString = removeBold(textString);
167 | textString = removeItalic(textString);
168 |
169 | // convert 'non breaking html spaces' into blanks. But preserve them
170 | // (don't remove white space)
171 | textString = textString.replaceAll(" ", " ");
172 | textString = textString.replaceAll("\\( ", "(");
173 | textString = textString.replaceAll(" \\)", ")");
174 |
175 | // find full stop near length of text
176 | int endOfTextIdx = textString.length();
177 |
178 | if (stopAtParagraph) {
179 | // only look at first paragraph for summary
180 | int paragraph = textString.indexOf("==");
181 | if (paragraph > 10) {
182 | endOfTextIdx = paragraph;
183 | }
184 | }
185 |
186 | //
187 | if (endOfTextIdx < 20 || endOfTextIdx > length) {
188 | endOfTextIdx = textString.lastIndexOf(".", length);
189 | if (endOfTextIdx < 0.7 * length) {
190 | endOfTextIdx = textString.lastIndexOf(" ", length);
191 | }
192 | }
193 |
194 | // add elipsis if we have shortened the article
195 | if (endOfTextIdx > -1 && endOfTextIdx < textString.length()) {
196 | textString = textString.substring(0, endOfTextIdx) + " (...)";
197 | }
198 |
199 | // trim trailing spaces and return
200 | return textString.trim();
201 | }
202 |
203 | /**
204 | * skips templates in wikipedia markup. Templates are enclosed within braces
205 | * {}. There might be nested templates within an other template.
206 | *
207 | * @param pText
208 | * : the wikipedia text with templates
209 | * @param pIdx
210 | * , pos in text to start with, MUST be a {
211 | * @return the idx into the text where the template ends, or the last
212 | * character in the text if it does not properly end.
213 | */
214 | static int skipTemplate(String pText, int pIdx) {
215 | // make sure we start with opening braces
216 | if (pText.charAt(pIdx) != '{') {
217 | return pIdx;
218 | }
219 |
220 | // counter for the braces we have opened, braces might be recursive
221 | // we use an iterative implementation, since it is a tiny little bit
222 | // faster
223 | int numOpenings = 1;
224 | // start with the next character
225 | int idx = pIdx + 1;
226 | // loop over the text starting from the next character till the end of
227 | // the template or the end of the text
228 | while (numOpenings > 0 && pText.length() > idx) {
229 | if (pText.charAt(idx) == '{') {
230 | numOpenings++;
231 | } else if (pText.charAt(idx) == '}') {
232 | numOpenings--;
233 | }
234 | idx++;
235 | }
236 | return idx;
237 | }
238 |
239 | /**
240 | * @param pText
241 | * @param pIdx
242 | * , pos in text to start with, MUST be a {
243 | * @return
244 | */
245 | static int skipHTMLElement(String pText, int pIdx) {
246 | if (pText.charAt(pIdx) != '<') {
247 | return pIdx;
248 | }
249 |
250 | int numOpenings = 1;
251 | int idx = pIdx + 1;
252 | while (numOpenings > 0 && pText.length() > idx) {
253 | if (pText.charAt(idx) == '<') {
254 | numOpenings++;
255 | } else if (pText.charAt(idx) == '>') {
256 | numOpenings--;
257 | }
258 | idx++;
259 | }
260 | return idx;
261 | }
262 |
263 | /**
264 | * @param pText
265 | * @param pIdx,
266 | * pos in text to start with, MUST be a '<'
267 | * @return
268 | */
269 | static int skipHTMLComment(String pText, int pIdx) {
270 | if (pText.charAt(pIdx) != '<' && pText.charAt(pIdx + 1) != '!') {
271 | return pIdx;
272 | }
273 |
274 | int idx = pIdx;
275 | while ((idx = pText.indexOf('-', idx)) > -1) {
276 | if (pText.length() < idx + 2) {
277 | return pText.length();
278 | }
279 | if (pText.charAt(idx) == '-' && pText.charAt(idx + 1) == '-'
280 | && pText.charAt(idx + 2) == '>') {
281 | return idx + 3;
282 | }
283 | idx++;
284 | }
285 | return idx;
286 | }
287 |
288 | private static String removeIndentAtBeginning(String pText) {
289 | pText = pText.trim();
290 | if (pText.startsWith(":")) {
291 | int lineFeed = pText.indexOf("\n");
292 | if (lineFeed > -1) {
293 | pText = pText.substring(lineFeed + 1);
294 | } else {
295 | // we may already have removed the linefeed
296 | // check for italics
297 | if (pText.startsWith(":''")) {
298 | int italic = pText.indexOf("''", 3);
299 | if (italic > -1) {
300 | pText = pText.substring(italic + 2);
301 | }
302 | }
303 | }
304 | }
305 | return pText;
306 | }
307 |
308 | private static int findEndOfLink(String pText, int pIdx) {
309 | int end = pText.indexOf("]]", pIdx);
310 | if (end == -1) {
311 | return pIdx;
312 | }
313 |
314 | int idx = pIdx;
315 | int openingIdx = pText.indexOf("[[", idx + 2);
316 | while (openingIdx > -1 && openingIdx < end) {
317 | idx = end;
318 | end = pText.indexOf("]]", end + 2);
319 | openingIdx = pText.indexOf("[[", idx);
320 | }
321 | if (end != -1) {
322 | idx = end;
323 | }
324 | return idx;
325 | }
326 |
327 | /**
328 | * removes sequences of whitespace and keeps only one whitespace character
329 | *
330 | * @param pString
331 | * @return
332 | */
333 | public static String removeWhiteSpace(String pString) {
334 | StringBuffer buf = new StringBuffer();
335 | char[] chars = pString.toCharArray();
336 | int counter = 0;
337 | for (int i = 0; i < chars.length; i++) {
338 | if (chars[i] == ' ') {
339 | if (counter == 0) {
340 | buf.append(chars[i]);
341 | }
342 | counter++;
343 | } else {
344 | buf.append(chars[i]);
345 | counter = 0;
346 | }
347 | }
348 | return buf.toString();
349 | }
350 |
351 | public static String removeBold(String pString) {
352 | return pString.replaceAll("'''", "");
353 | }
354 |
355 | public static String removeItalic(String pString) {
356 | return pString.replaceAll("''", "");
357 | }
358 |
359 | }
360 |
--------------------------------------------------------------------------------
/org/geonames/Toponym.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2008 Marc Wick, geonames.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package org.geonames;
18 |
19 | /**
20 | * a GeoNames toponym
21 | *
22 | * @author marc@geonames
23 | *
24 | */
25 | public class Toponym {
26 |
27 | private int geoNameId;
28 |
29 | private String name;
30 |
31 | private String alternateNames;
32 |
33 | private String continentCode;
34 |
35 | private String countryCode;
36 |
37 | private String countryName;
38 |
39 | private Long population;
40 |
41 | private Integer elevation;
42 |
43 | private FeatureClass featureClass;
44 |
45 | private String featureClassName;
46 |
47 | private String featureCode;
48 |
49 | private String featureCodeName;
50 |
51 | private double latitude;
52 |
53 | private double longitude;
54 |
55 | private String adminCode1;
56 | private String adminName1;
57 |
58 | private String adminCode2;
59 | private String adminName2;
60 |
61 | private String adminCode3;
62 | private String adminName3;
63 |
64 | private String adminCode4;
65 | private String adminName4;
66 |
67 | private String adminCode5;
68 | private String adminName5;
69 |
70 | private Timezone timezone;
71 |
72 | private Style style;
73 |
74 | private BoundingBox boundingBox;
75 |
76 | /**
77 | * @return the continentCode
78 | * @throws InsufficientStyleException
79 | */
80 | public String getContinentCode() throws InsufficientStyleException {
81 | if (continentCode == null && style != null
82 | && Style.LONG.compareTo(style) > 0) {
83 | throw new InsufficientStyleException(
84 | "continentCode not supported by style " + style.name());
85 | }
86 | return continentCode;
87 | }
88 |
89 | /**
90 | * @param continentCode
91 | * the continentCode to set
92 | */
93 | public void setContinentCode(String continentCode) {
94 | this.continentCode = continentCode;
95 | }
96 |
97 | /**
98 | * @return Returns the ISO 3166-1-alpha-2 countryCode.
99 | */
100 | public String getCountryCode() {
101 | return countryCode;
102 | }
103 |
104 | /**
105 | * @param countryCode
106 | * The ISO 3166-1-alpha-2 countryCode to set.
107 | */
108 | public void setCountryCode(String countryCode) {
109 | this.countryCode = countryCode;
110 | }
111 |
112 | /**
113 | * @return Returns the elevation in meter.
114 | */
115 | public Integer getElevation() throws InsufficientStyleException {
116 | if (elevation == null && style != null
117 | && Style.LONG.compareTo(style) > 0) {
118 | throw new InsufficientStyleException(
119 | "elevation not supported by style " + style.name());
120 | }
121 | return elevation;
122 | }
123 |
124 | /**
125 | * @param elevation
126 | * The elevation im meter to set.
127 | */
128 | public void setElevation(Integer elevation) {
129 | this.elevation = elevation;
130 | }
131 |
132 | /**
133 | * the feature class {@link FeatureClass}
134 | *
135 | * @see GeoNames Feature
136 | * Codes
137 | * @return Returns the featureClass.
138 | */
139 | public FeatureClass getFeatureClass() {
140 | return featureClass;
141 | }
142 |
143 | /**
144 | * @param featureClass
145 | * The featureClass to set.
146 | */
147 | public void setFeatureClass(FeatureClass featureClass) {
148 | this.featureClass = featureClass;
149 | }
150 |
151 | /**
152 | * @see GeoNames Feature
153 | * Codes
154 | * @return Returns the featureCode.
155 | */
156 | public String getFeatureCode() {
157 | return featureCode;
158 | }
159 |
160 | /**
161 | * @param featureCode
162 | * The featureCode to set.
163 | */
164 | public void setFeatureCode(String featureCode) {
165 | this.featureCode = featureCode;
166 | }
167 |
168 | /**
169 | * latitude in decimal degrees (wgs84)
170 | *
171 | * @return Returns the latitude.
172 | */
173 | public double getLatitude() {
174 | return latitude;
175 | }
176 |
177 | /**
178 | * @param latitude
179 | * The latitude to set.
180 | */
181 | public void setLatitude(double latitude) {
182 | this.latitude = latitude;
183 | }
184 |
185 | /**
186 | * longitude in decimal degrees (wgs84)
187 | *
188 | * @return Returns the longitude.
189 | */
190 | public double getLongitude() {
191 | return longitude;
192 | }
193 |
194 | /**
195 | * @param longitude
196 | * The longitude to set.
197 | */
198 | public void setLongitude(double longitude) {
199 | this.longitude = longitude;
200 | }
201 |
202 | /**
203 | * @return Returns the name.
204 | */
205 | public String getName() {
206 | return name;
207 | }
208 |
209 | /**
210 | * @param name
211 | * The name to set.
212 | */
213 | public void setName(String name) {
214 | this.name = name;
215 | }
216 |
217 | /**
218 | * @return Returns the population.
219 | */
220 | public Long getPopulation() throws InsufficientStyleException {
221 | if (population == null && style != null
222 | && Style.LONG.compareTo(style) > 0) {
223 | throw new InsufficientStyleException(
224 | "population not supported by style " + style.name());
225 | }
226 | return population;
227 | }
228 |
229 | /**
230 | * @param population
231 | * The population to set.
232 | */
233 | public void setPopulation(Long population) {
234 | this.population = population;
235 | }
236 |
237 | /**
238 | * @return Returns the geoNameId.
239 | */
240 | public int getGeoNameId() {
241 | return geoNameId;
242 | }
243 |
244 | /**
245 | * @param geoNameId
246 | * The geoNameId to set.
247 | */
248 | public void setGeoNameId(int geonameId) {
249 | this.geoNameId = geonameId;
250 | }
251 |
252 | /**
253 | * @return Returns the featureClassName.
254 | */
255 | public String getFeatureClassName() {
256 | return featureClassName;
257 | }
258 |
259 | /**
260 | * @param featureClassName
261 | * The featureClassName to set.
262 | */
263 | public void setFeatureClassName(String featureClassName) {
264 | this.featureClassName = featureClassName;
265 | }
266 |
267 | /**
268 | * @return Returns the featureCodeName.
269 | */
270 | public String getFeatureCodeName() {
271 | return featureCodeName;
272 | }
273 |
274 | /**
275 | * @param featureCodeName
276 | * The featureCodeName to set.
277 | */
278 | public void setFeatureCodeName(String featureCodeName) {
279 | this.featureCodeName = featureCodeName;
280 | }
281 |
282 | /**
283 | * @return Returns the countryName.
284 | */
285 | public String getCountryName() {
286 | return countryName;
287 | }
288 |
289 | /**
290 | * @param countryName
291 | * The countryName to set.
292 | */
293 | public void setCountryName(String countryName) {
294 | this.countryName = countryName;
295 | }
296 |
297 | /**
298 | * alternate names of this place as comma separated list
299 | *
300 | * @return the alternateNames as comma separated list
301 | */
302 | public String getAlternateNames() throws InsufficientStyleException {
303 | if (alternateNames == null && style != null
304 | && Style.LONG.compareTo(style) > 0) {
305 | throw new InsufficientStyleException(
306 | "alternateNames not supported by style " + style.name());
307 | }
308 | return alternateNames;
309 | }
310 |
311 | /**
312 | * @param alternateNames
313 | * the alternateNames to set
314 | */
315 | public void setAlternateNames(String alternateNames) {
316 | this.alternateNames = alternateNames;
317 | }
318 |
319 | public String toString() {
320 | StringBuilder str = new StringBuilder();
321 | str.append("geoNameId=" + geoNameId + ",");
322 | str.append("name=" + name + ",");
323 | if (alternateNames != null) {
324 | str.append("alternateNames=" + alternateNames + ",");
325 | }
326 | str.append("latitude=" + latitude + ",");
327 | str.append("longitude=" + longitude + ",");
328 | str.append("countryCode=" + countryCode + ",");
329 | str.append("population=" + population + ",");
330 | str.append("elevation=" + elevation + ",");
331 | str.append("featureClass=" + featureClass + ",");
332 | str.append("featureCode=" + featureCode);
333 | return str.toString();
334 | }
335 |
336 | /**
337 | * @return the adminCode1
338 | */
339 | public String getAdminCode1() throws InsufficientStyleException {
340 | if (adminCode1 == null && style != null
341 | && Style.LONG.compareTo(style) > 0) {
342 | throw new InsufficientStyleException(
343 | "adminCode1 not supported by style " + style.name());
344 | }
345 | return adminCode1;
346 | }
347 |
348 | /**
349 | * @param adminCode1
350 | * the adminCode1 to set
351 | */
352 | public void setAdminCode1(String adminCode1) {
353 | this.adminCode1 = adminCode1;
354 | }
355 |
356 | /**
357 | * @return the adminCode2
358 | */
359 | public String getAdminCode2() throws InsufficientStyleException {
360 | if (adminCode2 == null && style != null
361 | && Style.LONG.compareTo(style) > 0) {
362 | throw new InsufficientStyleException(
363 | "adminCode2 not supported by style " + style.name());
364 | }
365 | return adminCode2;
366 | }
367 |
368 | /**
369 | * @param adminCode2
370 | * the adminCode2 to set
371 | */
372 | public void setAdminCode2(String adminCode2) {
373 | this.adminCode2 = adminCode2;
374 | }
375 |
376 | /**
377 | * @return the adminCode3
378 | */
379 | public String getAdminCode3() throws InsufficientStyleException {
380 | if (adminCode3 == null && style != null
381 | && Style.LONG.compareTo(style) > 0) {
382 | throw new InsufficientStyleException(
383 | "adminCode3 not supported by style " + style.name());
384 | }
385 | return adminCode3;
386 | }
387 |
388 | /**
389 | * @param adminCode3
390 | * the adminCode3 to set
391 | */
392 | public void setAdminCode3(String adminCode3) {
393 | this.adminCode3 = adminCode3;
394 | }
395 |
396 | /**
397 | * @return the adminCode4
398 | */
399 | public String getAdminCode4() throws InsufficientStyleException {
400 | if (adminCode4 == null && style != null
401 | && Style.LONG.compareTo(style) > 0) {
402 | throw new InsufficientStyleException(
403 | "adminCode4 not supported by style " + style.name());
404 | }
405 | return adminCode4;
406 | }
407 |
408 | /**
409 | * @param adminCode4
410 | * the adminCode4 to set
411 | */
412 | public void setAdminCode4(String adminCode4) {
413 | this.adminCode4 = adminCode4;
414 | }
415 |
416 | /**
417 | * @return the adminCode5
418 | */
419 | public String getAdminCode5() {
420 | return adminCode5;
421 | }
422 |
423 | /**
424 | * @param adminCode5
425 | * the adminCode5 to set
426 | */
427 | public void setAdminCode5(String adminCode5) {
428 | this.adminCode5 = adminCode5;
429 | }
430 |
431 | /**
432 | * @return the timezone
433 | */
434 | public Timezone getTimezone() throws InsufficientStyleException {
435 | if (timezone == null && style != null
436 | && Style.LONG.compareTo(style) > 0) {
437 | throw new InsufficientStyleException(
438 | "alternateNames not supported by style " + style.name());
439 | }
440 | return timezone;
441 | }
442 |
443 | /**
444 | * @param timezone
445 | * the timezone to set
446 | */
447 | public void setTimezone(Timezone timezone) {
448 | this.timezone = timezone;
449 | }
450 |
451 | /**
452 | * @return the adminName1
453 | */
454 | public String getAdminName1() throws InsufficientStyleException {
455 | if (adminName1 == null && style != null
456 | && Style.LONG.compareTo(style) > 0) {
457 | throw new InsufficientStyleException(
458 | "adminName1 not supported by style " + style.name());
459 | }
460 | return adminName1;
461 | }
462 |
463 | /**
464 | * @param adminName1
465 | * the adminName1 to set
466 | */
467 | public void setAdminName1(String adminName1) {
468 | this.adminName1 = adminName1;
469 | }
470 |
471 | /**
472 | * @return the adminName2
473 | */
474 | public String getAdminName2() throws InsufficientStyleException {
475 | if (adminName2 == null && style != null
476 | && Style.LONG.compareTo(style) > 0) {
477 | throw new InsufficientStyleException(
478 | "adminName2 not supported by style " + style.name());
479 | }
480 | return adminName2;
481 | }
482 |
483 | /**
484 | * @param adminName2
485 | * the adminName2 to set
486 | */
487 | public void setAdminName2(String adminName2) {
488 | this.adminName2 = adminName2;
489 | }
490 |
491 | /**
492 | * @return the adminName3
493 | */
494 | public String getAdminName3() {
495 | return adminName3;
496 | }
497 |
498 | /**
499 | * @param adminName3
500 | * the adminName3 to set
501 | */
502 | public void setAdminName3(String adminName3) {
503 | this.adminName3 = adminName3;
504 | }
505 |
506 | /**
507 | * @return the adminName4
508 | */
509 | public String getAdminName4() {
510 | return adminName4;
511 | }
512 |
513 | /**
514 | * @param adminName4
515 | * the adminName4 to set
516 | */
517 | public void setAdminName4(String adminName4) {
518 | this.adminName4 = adminName4;
519 | }
520 |
521 | /**
522 | * @return the adminName5
523 | */
524 | public String getAdminName5() {
525 | return adminName5;
526 | }
527 |
528 | /**
529 | * @param adminName5
530 | * the adminName5 to set
531 | */
532 | public void setAdminName5(String adminName5) {
533 | this.adminName5 = adminName5;
534 | }
535 |
536 | /**
537 | * @return the style used when calling the web service that returned this
538 | * toponym.
539 | */
540 | public Style getStyle() {
541 | return style;
542 | }
543 |
544 | /**
545 | * @param style
546 | * the style to set
547 | */
548 | public void setStyle(Style style) {
549 | this.style = style;
550 | }
551 |
552 | /**
553 | * @return the boundingBox
554 | */
555 | public BoundingBox getBoundingBox() {
556 | return boundingBox;
557 | }
558 |
559 | /**
560 | * @param boundingBox
561 | * the boundingBox to set
562 | */
563 | public void setBoundingBox(BoundingBox boundingBox) {
564 | this.boundingBox = boundingBox;
565 | }
566 |
567 | }
568 |
--------------------------------------------------------------------------------
/org/geonames/WebService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2008-2012 Marc Wick, geonames.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package org.geonames;
18 |
19 | import java.io.BufferedReader;
20 | import java.io.IOException;
21 | import java.io.InputStream;
22 | import java.io.InputStreamReader;
23 | import java.lang.reflect.Field;
24 | import java.net.HttpURLConnection;
25 | import java.net.MalformedURLException;
26 | import java.net.Proxy;
27 | import java.net.URL;
28 | import java.net.URLConnection;
29 | import java.net.URLEncoder;
30 | import java.text.ParseException;
31 | import java.text.SimpleDateFormat;
32 | import java.util.ArrayList;
33 | import java.util.List;
34 | import java.util.TimeZone;
35 | import java.util.logging.Level;
36 | import java.util.logging.Logger;
37 |
38 | import org.jdom.Document;
39 | import org.jdom.Element;
40 | import org.jdom.JDOMException;
41 | import org.jdom.input.SAXBuilder;
42 |
43 | /**
44 | * provides static methods to access the GeoNames web
46 | * services.
47 | *
48 | * Note : values for some fields are only returned with sufficient {@link Style}
49 | * . Accessing these fields (admin codes and admin names, elevation,population)
50 | * will throw an {@link InsufficientStyleException} if the {@link Style} was not
51 | * sufficient.
52 | *
53 | * @author marc@geonames
54 | *
55 | */
56 | public class WebService {
57 |
58 | private static Logger logger = Logger.getLogger("org.geonames");
59 |
60 | private static String USER_AGENT = "gnwsc/1.1.14";
61 |
62 | private static boolean isAndroid = false;
63 |
64 | private static String geoNamesServer = "http://api.geonames.org";
65 |
66 | private static String geoNamesServerFailover = "http://api.geonames.org";
67 |
68 | private static long timeOfLastFailureMainServer;
69 |
70 | private static long averageConnectTime;
71 |
72 | private static long averageSampleSize = 20;
73 |
74 | private static Style defaultStyle = Style.MEDIUM;
75 |
76 | private static int readTimeOut = 120000;
77 |
78 | private static int connectTimeOut = 10000;
79 |
80 | private static String DATEFMT = "yyyy-MM-dd HH:mm:ss";
81 |
82 | private static Proxy proxy;
83 |
84 | static {
85 | USER_AGENT += " (";
86 | String os = System.getProperty("os.name");
87 | if (os != null) {
88 | USER_AGENT += os + ",";
89 | }
90 | String osVersion = System.getProperty("os.version");
91 | if (osVersion != null) {
92 | USER_AGENT += osVersion;
93 | }
94 | USER_AGENT += ")";
95 |
96 | // android version
97 | try {
98 | Class aClass = Class.forName("android.os.Build");
99 | if (aClass != null) {
100 | isAndroid = true;
101 | Field[] fields = aClass.getFields();
102 | if (fields != null) {
103 | for (Field field : fields) {
104 | if ("MODEL".equalsIgnoreCase(field.getName())) {
105 | USER_AGENT += "(" + field.get(aClass) + ", ";
106 | }
107 | }
108 | }
109 | aClass = Class.forName("android.os.Build$VERSION");
110 | if (aClass != null) {
111 | fields = aClass.getFields();
112 | if (fields != null) {
113 | for (Field field : fields) {
114 | if ("RELEASE".equalsIgnoreCase(field.getName())) {
115 | USER_AGENT += field.get(aClass);
116 | }
117 | }
118 | }
119 | }
120 | USER_AGENT += ")";
121 | }
122 | } catch (Throwable t) {
123 | }
124 | }
125 |
126 | /**
127 | * user name to pass to commercial web services for authentication and
128 | * authorization
129 | */
130 | private static String userName;
131 |
132 | /**
133 | * token to pass to as optional authentication parameter to the commercial
134 | * web services.
135 | */
136 | private static String token;
137 |
138 | /**
139 | * adds the username stored in a static variable to the url. It also adds a
140 | * token if one has been set with the static setter previously.
141 | *
142 | * @param url
143 | * @return url with the username appended
144 | */
145 | private static String addUserName(String url) {
146 | if (userName != null) {
147 | url = url + "&username=" + userName;
148 | }
149 | if (token != null) {
150 | url = url + "&token=" + token;
151 | }
152 | return url;
153 | }
154 |
155 | /**
156 | * adds the default style to the url. The default style can be set with the
157 | * static setter. It is 'MEDIUM' if not set.
158 | *
159 | * @param url
160 | * @return url with the style parameter appended
161 | */
162 | private static String addDefaultStyle(String url) {
163 | if (defaultStyle != Style.MEDIUM) {
164 | url = url + "&style=" + defaultStyle.name();
165 | }
166 | return url;
167 | }
168 |
169 | /**
170 | * returns the currently active server. Normally this is the main server, if
171 | * the main server recently failed then the failover server is returned. If
172 | * the main server is not available we don't want to try with every request
173 | * whether it is available again. We switch to the failover server and try
174 | * from time to time whether the main server is again accessible.
175 | *
176 | * @return
177 | */
178 | private static String getCurrentlyActiveServer() {
179 | if (timeOfLastFailureMainServer == 0) {
180 | // no problems with main server
181 | return geoNamesServer;
182 | }
183 | // we had problems with main server
184 | if (System.currentTimeMillis() - timeOfLastFailureMainServer > 1000l * 60l * 10l) {
185 | // but is was some time ago and we switch back to the main server to
186 | // retry. The problem may have been solved in the mean time.
187 | timeOfLastFailureMainServer = 0;
188 | return geoNamesServer;
189 | }
190 | if (System.currentTimeMillis() < timeOfLastFailureMainServer) {
191 | throw new Error("time of last failure cannot be in future.");
192 | }
193 | // the problems have been very recent and we continue with failover
194 | // server
195 | if (geoNamesServerFailover != null) {
196 | return geoNamesServerFailover;
197 | }
198 | return geoNamesServer;
199 | }
200 |
201 | /**
202 | * @return the isAndroid
203 | */
204 | public static boolean isAndroid() {
205 | return isAndroid;
206 | }
207 |
208 | /**
209 | * opens the connection to the url and sets the user agent. In case of an
210 | * IOException it checks whether a failover server is set and connects to
211 | * the failover server if it has been defined and if it is different from
212 | * the normal server.
213 | *
214 | * @param url
215 | * the url to connect to
216 | * @return returns the inputstream for the connection
217 | * @throws IOException
218 | */
219 | private static InputStream connect(String url) throws IOException {
220 | int status = 0;
221 | String currentlyActiveServer = getCurrentlyActiveServer();
222 | try {
223 | long begin = System.currentTimeMillis();
224 | HttpURLConnection httpConnection = null;
225 | if (proxy == null) {
226 | httpConnection = (HttpURLConnection) new URL(
227 | currentlyActiveServer + url).openConnection();
228 | } else {
229 | httpConnection = (HttpURLConnection) new URL(
230 | currentlyActiveServer + url).openConnection(proxy);
231 | }
232 | httpConnection.setConnectTimeout(connectTimeOut);
233 | httpConnection.setReadTimeout(readTimeOut);
234 | httpConnection.setRequestProperty("User-Agent", USER_AGENT);
235 | InputStream in = httpConnection.getInputStream();
236 | status = httpConnection.getResponseCode();
237 |
238 | if (status == 200) {
239 | long elapsedTime = System.currentTimeMillis() - begin;
240 | averageConnectTime = (averageConnectTime
241 | * (averageSampleSize - 1) + elapsedTime)
242 | / averageSampleSize;
243 | // if the average elapsed time is too long we switch server
244 | if (geoNamesServerFailover != null
245 | && averageConnectTime > 5000
246 | && !currentlyActiveServer
247 | .equals(geoNamesServerFailover)) {
248 | timeOfLastFailureMainServer = System.currentTimeMillis();
249 | }
250 | return in;
251 | }
252 | } catch (IOException e) {
253 | return tryFailoverServer(url, currentlyActiveServer, 0, e);
254 | }
255 | // we only get here if we had a statuscode <> 200
256 | IOException ioException = new IOException("status code " + status
257 | + " for " + url);
258 | return tryFailoverServer(url, currentlyActiveServer, status,
259 | ioException);
260 | }
261 |
262 | private static synchronized InputStream tryFailoverServer(String url,
263 | String currentlyActiveServer, int status, IOException e)
264 | throws MalformedURLException, IOException {
265 | // we cannot reach the server
266 | logger.log(Level.WARNING, "problems connecting to geonames server "
267 | + currentlyActiveServer, e);
268 | // is a failover server defined?
269 | if (geoNamesServerFailover == null
270 | // is it different from the one we are using?
271 | || currentlyActiveServer.equals(geoNamesServerFailover)) {
272 | if (currentlyActiveServer.equals(geoNamesServerFailover)) {
273 | // failover server is not accessible, we throw exception
274 | // and switch back to main server.
275 | timeOfLastFailureMainServer = 0;
276 | }
277 | throw e;
278 | }
279 | timeOfLastFailureMainServer = System.currentTimeMillis();
280 | logger.info("trying to connect to failover server "
281 | + geoNamesServerFailover);
282 | // try failover server
283 | URLConnection conn = null;
284 | if (proxy == null) {
285 | conn = new URL(geoNamesServerFailover + url).openConnection();
286 | } else {
287 | conn = new URL(geoNamesServerFailover + url).openConnection(proxy);
288 | }
289 |
290 | String userAgent = USER_AGENT + " failover from " + geoNamesServer;
291 | if (status != 0) {
292 | userAgent += " " + status;
293 | }
294 | conn.setRequestProperty("User-Agent", userAgent);
295 | InputStream in = conn.getInputStream();
296 | return in;
297 | }
298 |
299 | private static Element connectAndParse(String url)
300 | throws GeoNamesException, IOException, JDOMException {
301 | SAXBuilder parser = new SAXBuilder();
302 | Document doc = parser.build(connect(url));
303 | try {
304 | Element root = rootAndCheckException(doc);
305 | return root;
306 | } catch (GeoNamesException geoNamesException) {
307 | if (geoNamesException.getExceptionCode() == 13
308 | || (geoNamesException.getMessage() != null && geoNamesException
309 | .getMessage()
310 | .indexOf(
311 | "canceling statement due to statement timeout") > -1)) {
312 | String currentlyActiveServer = getCurrentlyActiveServer();
313 | if (geoNamesServerFailover != null
314 | && !currentlyActiveServer
315 | .equals(geoNamesServerFailover)) {
316 | timeOfLastFailureMainServer = System.currentTimeMillis();
317 | doc = parser.build(connect(url));
318 | Element root = rootAndCheckException(doc);
319 | return root;
320 | }
321 | }
322 | throw geoNamesException;
323 | }
324 | }
325 |
326 | private static Element rootAndCheckException(Document doc)
327 | throws GeoNamesException {
328 | Element root = doc.getRootElement();
329 | checkException(root);
330 | return root;
331 | }
332 |
333 | private static void checkException(Element root) throws GeoNamesException {
334 | Element message = root.getChild("status");
335 | if (message != null) {
336 | int code = 0;
337 | try {
338 | code = Integer.parseInt(message.getAttributeValue("value"));
339 | } catch (NumberFormatException numberFormatException) {
340 | }
341 | throw new GeoNamesException(code,
342 | message.getAttributeValue("message"));
343 | }
344 | }
345 |
346 | /**
347 | * check whether we can parse an exception and throw it if we can
348 | *
349 | * if the line starts with ERR: then we have a geonames exception.
350 | *
351 | * @param line
352 | * @throws GeoNamesException
353 | */
354 | private static void checkException(String line) throws GeoNamesException {
355 | if (line.startsWith("ERR:")) {
356 | String[] terms = line.split(":");
357 | if (terms.length == 3) {
358 | throw new GeoNamesException(Integer.parseInt(terms[1]),
359 | terms[2]);
360 | }
361 | throw new GeoNamesException("unhandled exception");
362 | }
363 | }
364 |
365 | private static Toponym getToponymFromElement(Element toponymElement) {
366 | Toponym toponym = new Toponym();
367 |
368 | toponym.setName(toponymElement.getChildText("name"));
369 | toponym.setAlternateNames(toponymElement.getChildText("alternateNames"));
370 | toponym.setLatitude(Double.parseDouble(toponymElement
371 | .getChildText("lat")));
372 | toponym.setLongitude(Double.parseDouble(toponymElement
373 | .getChildText("lng")));
374 |
375 | String geonameId = toponymElement.getChildText("geonameId");
376 | if (geonameId != null) {
377 | toponym.setGeoNameId(Integer.parseInt(geonameId));
378 | }
379 |
380 | toponym.setContinentCode(toponymElement.getChildText("continentCode"));
381 | toponym.setCountryCode(toponymElement.getChildText("countryCode"));
382 | toponym.setCountryName(toponymElement.getChildText("countryName"));
383 |
384 | toponym.setFeatureClass(FeatureClass.fromValue(toponymElement
385 | .getChildText("fcl")));
386 | toponym.setFeatureCode(toponymElement.getChildText("fcode"));
387 |
388 | toponym.setFeatureClassName(toponymElement.getChildText("fclName"));
389 | toponym.setFeatureCodeName(toponymElement.getChildText("fCodeName"));
390 |
391 | String population = toponymElement.getChildText("population");
392 | if (population != null && !"".equals(population)) {
393 | toponym.setPopulation(Long.parseLong(population));
394 | }
395 | String elevation = toponymElement.getChildText("elevation");
396 | if (elevation != null && !"".equals(elevation)) {
397 | toponym.setElevation(Integer.parseInt(elevation));
398 | }
399 |
400 | toponym.setAdminCode1(toponymElement.getChildText("adminCode1"));
401 | toponym.setAdminName1(toponymElement.getChildText("adminName1"));
402 | toponym.setAdminCode2(toponymElement.getChildText("adminCode2"));
403 | toponym.setAdminName2(toponymElement.getChildText("adminName2"));
404 | toponym.setAdminCode3(toponymElement.getChildText("adminCode3"));
405 | toponym.setAdminName3(toponymElement.getChildText("adminName3"));
406 | toponym.setAdminCode4(toponymElement.getChildText("adminCode4"));
407 | toponym.setAdminName4(toponymElement.getChildText("adminName4"));
408 | toponym.setAdminCode5(toponymElement.getChildText("adminCode5"));
409 | toponym.setAdminName5(toponymElement.getChildText("adminName5"));
410 |
411 | Element timezoneElement = toponymElement.getChild("timezone");
412 | if (timezoneElement != null) {
413 | Timezone timezone = new Timezone();
414 | timezone.setTimezoneId(timezoneElement.getValue());
415 | timezone.setDstOffset(Double.parseDouble(timezoneElement
416 | .getAttributeValue("dstOffset")));
417 | timezone.setGmtOffset(Double.parseDouble(timezoneElement
418 | .getAttributeValue("gmtOffset")));
419 | toponym.setTimezone(timezone);
420 | }
421 |
422 | Element bboxElement = toponymElement.getChild("bbox");
423 | if (bboxElement != null) {
424 | BoundingBox boundingBox = new BoundingBox(
425 | Double.parseDouble(bboxElement.getChildText("west")),
426 | Double.parseDouble(bboxElement.getChildText("east")),
427 | Double.parseDouble(bboxElement.getChildText("south")),
428 | Double.parseDouble(bboxElement.getChildText("north")));
429 | toponym.setBoundingBox(boundingBox);
430 | }
431 |
432 | return toponym;
433 | }
434 |
435 | private static WikipediaArticle getWikipediaArticleFromElement(
436 | Element wikipediaArticleElement) {
437 | WikipediaArticle wikipediaArticle = new WikipediaArticle();
438 | wikipediaArticle.setLanguage(wikipediaArticleElement
439 | .getChildText("lang"));
440 | wikipediaArticle
441 | .setTitle(wikipediaArticleElement.getChildText("title"));
442 | wikipediaArticle.setSummary(wikipediaArticleElement
443 | .getChildText("summary"));
444 | wikipediaArticle.setFeature(wikipediaArticleElement
445 | .getChildText("feature"));
446 | wikipediaArticle.setWikipediaUrl(wikipediaArticleElement
447 | .getChildText("wikipediaUrl"));
448 | wikipediaArticle.setThumbnailImg(wikipediaArticleElement
449 | .getChildText("thumbnailImg"));
450 |
451 | wikipediaArticle.setLatitude(Double.parseDouble(wikipediaArticleElement
452 | .getChildText("lat")));
453 | wikipediaArticle.setLongitude(Double
454 | .parseDouble(wikipediaArticleElement.getChildText("lng")));
455 |
456 | wikipediaArticle.setRank(Integer.parseInt(wikipediaArticleElement
457 | .getChildText("rank")));
458 |
459 | String population = wikipediaArticleElement.getChildText("population");
460 | if (population != null && !"".equals(population)) {
461 | wikipediaArticle.setPopulation(Integer.parseInt(population));
462 | }
463 |
464 | String elevation = wikipediaArticleElement.getChildText("elevation");
465 | if (elevation != null && !"".equals(elevation)) {
466 | wikipediaArticle.setElevation(Integer.parseInt(elevation));
467 | }
468 | return wikipediaArticle;
469 | }
470 |
471 | private static TimeZone utc = TimeZone.getTimeZone("UTC");
472 |
473 | private static WeatherObservation getWeatherObservationFromElement(
474 | Element weatherObservationElement) throws ParseException {
475 | WeatherObservation weatherObservation = new WeatherObservation();
476 | weatherObservation.setObservation(weatherObservationElement
477 | .getChildText("observation"));
478 | SimpleDateFormat df = new SimpleDateFormat(DATEFMT);
479 | df.setTimeZone(utc);
480 | weatherObservation.setObservationTime(df
481 | .parse(weatherObservationElement
482 | .getChildText("observationTime")));
483 | weatherObservation.setStationName(weatherObservationElement
484 | .getChildText("stationName"));
485 | weatherObservation.setIcaoCode(weatherObservationElement
486 | .getChildText("ICAO"));
487 | weatherObservation.setCountryCode(weatherObservationElement
488 | .getChildText("countryCode"));
489 | String elevation = weatherObservationElement.getChildText("elevation");
490 | if (elevation != null && !"".equals(elevation)) {
491 | weatherObservation.setElevation(Integer.parseInt(elevation));
492 | }
493 | weatherObservation.setLatitude(Double
494 | .parseDouble(weatherObservationElement.getChildText("lat")));
495 | weatherObservation.setLongitude(Double
496 | .parseDouble(weatherObservationElement.getChildText("lng")));
497 | String temperature = weatherObservationElement
498 | .getChildText("temperature");
499 | if (temperature != null && !"".equals(temperature)) {
500 | weatherObservation.setTemperature(Double.parseDouble(temperature));
501 | }
502 | String dewPoint = weatherObservationElement.getChildText("dewPoint");
503 | if (dewPoint != null && !"".equals(dewPoint)) {
504 | weatherObservation.setDewPoint(Double.parseDouble(dewPoint));
505 | }
506 | String humidity = weatherObservationElement.getChildText("humidity");
507 | if (humidity != null && !"".equals(humidity)) {
508 | weatherObservation.setHumidity(Double.parseDouble(humidity));
509 | }
510 | weatherObservation.setClouds(weatherObservationElement
511 | .getChildText("clouds"));
512 | weatherObservation.setWeatherCondition(weatherObservationElement
513 | .getChildText("weatherCondition"));
514 | weatherObservation.setWindSpeed(weatherObservationElement
515 | .getChildText("windSpeed"));
516 | return weatherObservation;
517 |
518 | }
519 |
520 | /**
521 | * returns a list of postal codes for the given parameters. This method is
522 | * for convenience.
523 | *
524 | * @param postalCode
525 | * @param placeName
526 | * @param countryCode
527 | * @return
528 | * @throws Exception
529 | */
530 | public static List postalCodeSearch(String postalCode,
531 | String placeName, String countryCode) throws Exception {
532 | PostalCodeSearchCriteria postalCodeSearchCriteria = new PostalCodeSearchCriteria();
533 | postalCodeSearchCriteria.setPostalCode(postalCode);
534 | postalCodeSearchCriteria.setPlaceName(placeName);
535 | postalCodeSearchCriteria.setCountryCode(countryCode);
536 | return postalCodeSearch(postalCodeSearchCriteria);
537 | }
538 |
539 | /**
540 | * returns a list of postal codes for the given search criteria matching a
541 | * full text search on the GeoNames postal codes database.
542 | *
543 | * @param postalCodeSearchCriteria
544 | * @return
545 | * @throws Exception
546 | */
547 | public static List postalCodeSearch(
548 | PostalCodeSearchCriteria postalCodeSearchCriteria) throws Exception {
549 | List postalCodes = new ArrayList();
550 |
551 | String url = "/postalCodeSearch?";
552 | if (postalCodeSearchCriteria.getPostalCode() != null) {
553 | url = url
554 | + "postalcode="
555 | + URLEncoder.encode(
556 | postalCodeSearchCriteria.getPostalCode(), "UTF8");
557 | }
558 | if (postalCodeSearchCriteria.getPlaceName() != null) {
559 | if (!url.endsWith("&")) {
560 | url = url + "&";
561 | }
562 | url = url
563 | + "placename="
564 | + URLEncoder.encode(
565 | postalCodeSearchCriteria.getPlaceName(), "UTF8");
566 | }
567 | if (postalCodeSearchCriteria.getAdminCode1() != null) {
568 | url = url
569 | + "&adminCode1="
570 | + URLEncoder.encode(
571 | postalCodeSearchCriteria.getAdminCode1(), "UTF8");
572 | }
573 |
574 | if (postalCodeSearchCriteria.getCountryCode() != null) {
575 | if (!url.endsWith("&")) {
576 | url = url + "&";
577 | }
578 | url = url + "country=" + postalCodeSearchCriteria.getCountryCode();
579 | }
580 | if (postalCodeSearchCriteria.getCountryBias() != null) {
581 | if (!url.endsWith("&")) {
582 | url = url + "&";
583 | }
584 | url = url + "countryBias="
585 | + postalCodeSearchCriteria.getCountryBias();
586 | }
587 | if (postalCodeSearchCriteria.getMaxRows() > 0) {
588 | url = url + "&maxRows=" + postalCodeSearchCriteria.getMaxRows();
589 | }
590 | if (postalCodeSearchCriteria.getStartRow() > 0) {
591 | url = url + "&startRow=" + postalCodeSearchCriteria.getStartRow();
592 | }
593 | if (postalCodeSearchCriteria.isOROperator()) {
594 | url = url + "&operator=OR";
595 | }
596 | if (postalCodeSearchCriteria.isReduced() != null) {
597 | url = url + "&isReduced="
598 | + postalCodeSearchCriteria.isReduced().toString();
599 | }
600 | if (postalCodeSearchCriteria.getBoundingBox() != null) {
601 | url = url + "&east="
602 | + postalCodeSearchCriteria.getBoundingBox().getEast();
603 | url = url + "&west="
604 | + postalCodeSearchCriteria.getBoundingBox().getWest();
605 | url = url + "&north="
606 | + postalCodeSearchCriteria.getBoundingBox().getNorth();
607 | url = url + "&south="
608 | + postalCodeSearchCriteria.getBoundingBox().getSouth();
609 | }
610 |
611 | url = addUserName(url);
612 |
613 | Element root = connectAndParse(url);
614 | for (Object obj : root.getChildren("code")) {
615 | Element codeElement = (Element) obj;
616 | PostalCode code = getPostalCodeFromElement(codeElement);
617 | postalCodes.add(code);
618 | }
619 |
620 | return postalCodes;
621 | }
622 |
623 | /**
624 | * returns a list of postal codes
625 | *
626 | * @param postalCodeSearchCriteria
627 | * @return
628 | * @throws Exception
629 | */
630 | public static List findNearbyPostalCodes(
631 | PostalCodeSearchCriteria postalCodeSearchCriteria) throws Exception {
632 |
633 | List postalCodes = new ArrayList();
634 |
635 | String url = "/findNearbyPostalCodes?";
636 | if (postalCodeSearchCriteria.getPostalCode() != null) {
637 | url = url
638 | + "&postalcode="
639 | + URLEncoder.encode(
640 | postalCodeSearchCriteria.getPostalCode(), "UTF8");
641 | }
642 | if (postalCodeSearchCriteria.getPlaceName() != null) {
643 | url = url
644 | + "&placename="
645 | + URLEncoder.encode(
646 | postalCodeSearchCriteria.getPlaceName(), "UTF8");
647 | }
648 | if (postalCodeSearchCriteria.getCountryCode() != null) {
649 | url = url + "&country=" + postalCodeSearchCriteria.getCountryCode();
650 | }
651 |
652 | if (postalCodeSearchCriteria.getLatitude() != null) {
653 | url = url + "&lat=" + postalCodeSearchCriteria.getLatitude();
654 | }
655 | if (postalCodeSearchCriteria.getLongitude() != null) {
656 | url = url + "&lng=" + postalCodeSearchCriteria.getLongitude();
657 | }
658 | if (postalCodeSearchCriteria.getStyle() != null) {
659 | url = url + "&style=" + postalCodeSearchCriteria.getStyle();
660 | }
661 | if (postalCodeSearchCriteria.getMaxRows() > 0) {
662 | url = url + "&maxRows=" + postalCodeSearchCriteria.getMaxRows();
663 | }
664 |
665 | if (postalCodeSearchCriteria.getRadius() > 0) {
666 | url = url + "&radius=" + postalCodeSearchCriteria.getRadius();
667 | }
668 | url = addUserName(url);
669 |
670 | Element root = connectAndParse(url);
671 | for (Object obj : root.getChildren("code")) {
672 | Element codeElement = (Element) obj;
673 | PostalCode code = getPostalCodeFromElement(codeElement);
674 | if (codeElement.getChildText("distance") != null) {
675 | code.setDistance(Double.parseDouble(codeElement
676 | .getChildText("distance")));
677 | }
678 | postalCodes.add(code);
679 | }
680 |
681 | return postalCodes;
682 | }
683 |
684 | private static PostalCode getPostalCodeFromElement(Element codeElement)
685 | throws ParseException {
686 | PostalCode code = new PostalCode();
687 | code.setPostalCode(codeElement.getChildText("postalcode"));
688 | code.setPlaceName(codeElement.getChildText("name"));
689 | code.setCountryCode(codeElement.getChildText("countryCode"));
690 |
691 | code.setLatitude(Double.parseDouble(codeElement.getChildText("lat")));
692 | code.setLongitude(Double.parseDouble(codeElement.getChildText("lng")));
693 |
694 | code.setAdminName1(codeElement.getChildText("adminName1"));
695 | code.setAdminCode1(codeElement.getChildText("adminCode1"));
696 | code.setAdminName2(codeElement.getChildText("adminName2"));
697 | code.setAdminCode2(codeElement.getChildText("adminCode2"));
698 | code.setAdminName3(codeElement.getChildText("adminName3"));
699 | code.setAdminCode3(codeElement.getChildText("adminCode3"));
700 | return code;
701 | }
702 |
703 | /**
704 | * convenience method for
705 | * {@link #findNearbyPlaceName(double,double,double,int)}
706 | *
707 | * @param latitude
708 | * @param longitude
709 | * @return
710 | * @throws IOException
711 | * @throws Exception
712 | */
713 | public static List findNearbyPlaceName(double latitude,
714 | double longitude) throws IOException, Exception {
715 | return findNearbyPlaceName(latitude, longitude, 0, 0);
716 | }
717 |
718 | public static List findNearbyPlaceName(double latitude,
719 | double longitude, double radius, int maxRows) throws IOException,
720 | Exception {
721 | List places = new ArrayList();
722 |
723 | String url = "/findNearbyPlaceName?";
724 |
725 | url = url + "&lat=" + latitude;
726 | url = url + "&lng=" + longitude;
727 | if (radius > 0) {
728 | url = url + "&radius=" + radius;
729 | }
730 | if (maxRows > 0) {
731 | url = url + "&maxRows=" + maxRows;
732 | }
733 | url = addUserName(url);
734 | url = addDefaultStyle(url);
735 |
736 | Element root = connectAndParse(url);
737 | for (Object obj : root.getChildren("geoname")) {
738 | Element toponymElement = (Element) obj;
739 | Toponym toponym = getToponymFromElement(toponymElement);
740 | places.add(toponym);
741 | }
742 |
743 | return places;
744 | }
745 |
746 | public static List findNearby(double latitude, double longitude,
747 | FeatureClass featureClass, String[] featureCodes)
748 | throws IOException, Exception {
749 | return findNearby(latitude, longitude, 0, featureClass, featureCodes,
750 | null, 0);
751 | }
752 |
753 | /* Overload function to allow backward compatibility */
754 | /**
755 | * Based on the following inforamtion: Webservice Type : REST
756 | * api.geonames.org/findNearbyWikipedia? Parameters : lang : language code
757 | * (around 240 languages) (default = en) lat,lng, radius (in km), maxRows
758 | * (default = 10) featureClass featureCode Example:
759 | * http://api.geonames.org/findNearby?lat=47.3&lng=9
760 | *
761 | * @param: latitude
762 | * @param: longitude
763 | * @param: radius
764 | * @param: feature Class
765 | * @param: feature Codes
766 | * @param: language
767 | * @param: maxRows
768 | * @return: list of wikipedia articles
769 | * @throws: Exception
770 | */
771 | public static List findNearby(double latitude, double longitude,
772 | double radius, FeatureClass featureClass, String[] featureCodes,
773 | String language, int maxRows) throws IOException, Exception {
774 | List places = new ArrayList();
775 |
776 | String url = "/findNearby?";
777 |
778 | url += "&lat=" + latitude;
779 | url += "&lng=" + longitude;
780 | if (radius > 0) {
781 | url = url + "&radius=" + radius;
782 | }
783 | if (maxRows > 0) {
784 | url = url + "&maxRows=" + maxRows;
785 | }
786 |
787 | if (language != null) {
788 | url = url + "&lang=" + language;
789 | }
790 |
791 | if (featureClass != null) {
792 | url += "&featureClass=" + featureClass;
793 | }
794 | if (featureCodes != null && featureCodes.length > 0) {
795 | for (String featureCode : featureCodes) {
796 | url += "&featureCode=" + featureCode;
797 | }
798 | }
799 |
800 | url = addUserName(url);
801 | url = addDefaultStyle(url);
802 |
803 | Element root = connectAndParse(url);
804 | for (Object obj : root.getChildren("geoname")) {
805 | Element toponymElement = (Element) obj;
806 | Toponym toponym = getToponymFromElement(toponymElement);
807 | places.add(toponym);
808 | }
809 |
810 | return places;
811 | }
812 |
813 | /**
814 | *
815 | * @param geoNameId
816 | * @param language
817 | * - optional
818 | * @param style
819 | * - optional
820 | * @return the toponym for the geoNameId
821 | * @throws IOException
822 | * @throws Exception
823 | */
824 | public static Toponym get(int geoNameId, String language, String style)
825 | throws IOException, Exception {
826 | String url = "/get?";
827 |
828 | url += "geonameId=" + geoNameId;
829 |
830 | if (language != null) {
831 | url = url + "&lang=" + language;
832 | }
833 |
834 | if (style != null) {
835 | url = url + "&style=" + style;
836 | } else {
837 | url = addDefaultStyle(url);
838 | }
839 | url = addUserName(url);
840 |
841 | Element root = connectAndParse(url);
842 | Toponym toponym = getToponymFromElement(root);
843 | return toponym;
844 | }
845 |
846 | /**
847 | * for US only
848 | *
849 | * @param latitude
850 | * @param longitude
851 | * @return
852 | * @throws IOException
853 | * @throws Exception
854 | */
855 | public static Address findNearestAddress(double latitude, double longitude)
856 | throws IOException, Exception {
857 |
858 | String url = "/findNearestAddress?";
859 |
860 | url = url + "&lat=" + latitude;
861 | url = url + "&lng=" + longitude;
862 | url = addUserName(url);
863 |
864 | Element root = connectAndParse(url);
865 | for (Object obj : root.getChildren("address")) {
866 | Element codeElement = (Element) obj;
867 | Address address = new Address();
868 | address.setStreet(codeElement.getChildText("street"));
869 | address.setStreetNumber(codeElement.getChildText("streetNumber"));
870 | address.setMtfcc(codeElement.getChildText("mtfcc"));
871 |
872 | address.setPostalCode(codeElement.getChildText("postalcode"));
873 | address.setPlaceName(codeElement.getChildText("placename"));
874 | address.setCountryCode(codeElement.getChildText("countryCode"));
875 |
876 | address.setLatitude(Double.parseDouble(codeElement
877 | .getChildText("lat")));
878 | address.setLongitude(Double.parseDouble(codeElement
879 | .getChildText("lng")));
880 |
881 | address.setAdminName1(codeElement.getChildText("adminName1"));
882 | address.setAdminCode1(codeElement.getChildText("adminCode1"));
883 | address.setAdminName2(codeElement.getChildText("adminName2"));
884 | address.setAdminCode2(codeElement.getChildText("adminCode2"));
885 |
886 | address.setDistance(Double.parseDouble(codeElement
887 | .getChildText("distance")));
888 |
889 | return address;
890 | }
891 |
892 | return null;
893 | }
894 |
895 | public static Intersection findNearestIntersection(double latitude,
896 | double longitude) throws Exception {
897 | return findNearestIntersection(latitude, longitude, 0);
898 | }
899 |
900 | public static Intersection findNearestIntersection(double latitude,
901 | double longitude, double radius) throws Exception {
902 |
903 | String url = "/findNearestIntersection?";
904 |
905 | url = url + "&lat=" + latitude;
906 | url = url + "&lng=" + longitude;
907 | if (radius > 0) {
908 | url = url + "&radius=" + radius;
909 | }
910 | url = addUserName(url);
911 |
912 | Element root = connectAndParse(url);
913 | for (Object obj : root.getChildren("intersection")) {
914 | Element e = (Element) obj;
915 | Intersection intersection = new Intersection();
916 | intersection.setStreet1(e.getChildText("street1"));
917 | intersection.setStreet2(e.getChildText("street2"));
918 | intersection.setLatitude(Double.parseDouble(e.getChildText("lat")));
919 | intersection
920 | .setLongitude(Double.parseDouble(e.getChildText("lng")));
921 | intersection.setDistance(Double.parseDouble(e
922 | .getChildText("distance")));
923 | intersection.setPostalCode(e.getChildText("postalcode"));
924 | intersection.setPlaceName(e.getChildText("placename"));
925 | intersection.setCountryCode(e.getChildText("countryCode"));
926 | intersection.setAdminName2(e.getChildText("adminName2"));
927 | intersection.setAdminCode1(e.getChildText("adminCode1"));
928 | intersection.setAdminName1(e.getChildText("adminName1"));
929 | return intersection;
930 | }
931 | return null;
932 | }
933 |
934 | /**
935 | *
936 | * @see web service documentation
939 | *
940 | * @param latitude
941 | * @param longitude
942 | * @param radius
943 | * @return
944 | * @throws Exception
945 | */
946 | public static List findNearbyStreets(double latitude,
947 | double longitude, double radius) throws Exception {
948 |
949 | String url = "/findNearbyStreets?";
950 |
951 | url = url + "&lat=" + latitude;
952 | url = url + "&lng=" + longitude;
953 | if (radius > 0) {
954 | url = url + "&radius=" + radius;
955 | }
956 | url = addUserName(url);
957 |
958 | List segments = new ArrayList();
959 |
960 | Element root = connectAndParse(url);
961 | for (Object obj : root.getChildren("streetSegment")) {
962 | Element e = (Element) obj;
963 | StreetSegment streetSegment = new StreetSegment();
964 | String line = e.getChildText("line");
965 | String[] points = line.split(",");
966 | double[] latArray = new double[points.length];
967 | double[] lngArray = new double[points.length];
968 | for (int i = 0; i < points.length; i++) {
969 | String[] coords = points[i].split(" ");
970 | lngArray[i] = Double.parseDouble(coords[0]);
971 | latArray[i] = Double.parseDouble(coords[1]);
972 | }
973 |
974 | streetSegment.setCfcc(e.getChildText("cfcc"));
975 | streetSegment.setName(e.getChildText("name"));
976 | streetSegment.setFraddl(e.getChildText("fraddl"));
977 | streetSegment.setFraddr(e.getChildText("fraddr"));
978 | streetSegment.setToaddl(e.getChildText("toaddl"));
979 | streetSegment.setToaddr(e.getChildText("toaddr"));
980 | streetSegment.setPostalCode(e.getChildText("postalcode"));
981 | streetSegment.setPlaceName(e.getChildText("placename"));
982 | streetSegment.setCountryCode(e.getChildText("countryCode"));
983 | streetSegment.setAdminName2(e.getChildText("adminName2"));
984 | streetSegment.setAdminCode1(e.getChildText("adminCode1"));
985 | streetSegment.setAdminName1(e.getChildText("adminName1"));
986 | segments.add(streetSegment);
987 | }
988 | return segments;
989 | }
990 |
991 | public static List findNearbyStreetsOSM(double latitude,
992 | double longitude, double radius) throws Exception {
993 |
994 | String url = "/findNearbyStreetsOSM?";
995 |
996 | url = url + "&lat=" + latitude;
997 | url = url + "&lng=" + longitude;
998 | if (radius > 0) {
999 | url = url + "&radius=" + radius;
1000 | }
1001 | url = addUserName(url);
1002 |
1003 | List segments = new ArrayList();
1004 |
1005 | Element root = connectAndParse(url);
1006 | for (Object obj : root.getChildren("streetSegment")) {
1007 | Element e = (Element) obj;
1008 | StreetSegment streetSegment = new StreetSegment();
1009 | String line = e.getChildText("line");
1010 | String[] points = line.split(",");
1011 | double[] latArray = new double[points.length];
1012 | double[] lngArray = new double[points.length];
1013 | for (int i = 0; i < points.length; i++) {
1014 | String[] coords = points[i].split(" ");
1015 | lngArray[i] = Double.parseDouble(coords[0]);
1016 | latArray[i] = Double.parseDouble(coords[1]);
1017 | }
1018 |
1019 | streetSegment.setName(e.getChildText("name"));
1020 | segments.add(streetSegment);
1021 | }
1022 | return segments;
1023 | }
1024 |
1025 | /**
1026 | * Find the nearest address for a given lat/lng pair. Supports several countries.
1027 | *
1028 | * See documentation for the list of supported countries:
1029 | *
1030 | * * @see address
1031 | * web service documentation
1032 | *
1033 | *
1034 | * @param latitude
1035 | * @param longitude
1036 | * @return
1037 | * @throws IOException
1038 | * @throws Exception
1039 | */
1040 | public static Address address(double latitude, double longitude)
1041 | throws IOException, Exception {
1042 |
1043 | String url = "/address?";
1044 |
1045 | url = url + "&lat=" + latitude;
1046 | url = url + "&lng=" + longitude;
1047 | url = addUserName(url);
1048 |
1049 | Element root = connectAndParse(url);
1050 | for (Object obj : root.getChildren("address")) {
1051 | Element codeElement = (Element) obj;
1052 | Address address = new Address();
1053 | address.setStreet(codeElement.getChildText("street"));
1054 | address.setStreetNumber(codeElement.getChildText("houseNumber"));
1055 |
1056 | address.setPostalCode(codeElement.getChildText("postalcode"));
1057 | address.setPlaceName(codeElement.getChildText("locality"));
1058 | address.setCountryCode(codeElement.getChildText("countryCode"));
1059 |
1060 | address.setLatitude(Double.parseDouble(codeElement
1061 | .getChildText("lat")));
1062 | address.setLongitude(Double.parseDouble(codeElement
1063 | .getChildText("lng")));
1064 |
1065 | address.setAdminName1(codeElement.getChildText("adminName1"));
1066 | address.setAdminCode1(codeElement.getChildText("adminCode1"));
1067 | address.setAdminName2(codeElement.getChildText("adminName2"));
1068 | address.setAdminCode2(codeElement.getChildText("adminCode2"));
1069 | address.setAdminName3(codeElement.getChildText("adminName3"));
1070 | address.setAdminCode3(codeElement.getChildText("adminCode3"));
1071 |
1072 | address.setDistance(Double.parseDouble(codeElement
1073 | .getChildText("distance")));
1074 |
1075 | return address;
1076 | }
1077 |
1078 | return null;
1079 | }
1080 |
1081 | /**
1082 | * Returns location lat/lng and admin information for a given address.
1083 | *
1084 | * See documentation for the list of supported countries:
1085 | *
1086 | * * @see geoCodeAddress
1087 | * web service documentation
1088 | *
1089 | * @param q
1090 | * @param country
1091 | * @param postalcode
1092 | * @return
1093 | * @throws IOException
1094 | * @throws Exception
1095 | */
1096 | public static Address geoCodeAddress(String q, String country, String postalcode)
1097 | throws IOException, Exception {
1098 |
1099 | String url = "/geoCodeAddress?";
1100 |
1101 | url = url + "&q=" + URLEncoder.encode(q, "UTF8");
1102 | if (country != null && !country.isEmpty()) {
1103 | url = url + "&country=" + country;
1104 | }
1105 | if (postalcode != null && !postalcode.isEmpty()) {
1106 | url = url + "&postalcode=" + URLEncoder.encode(postalcode, "UTF8");
1107 | }
1108 | url = addUserName(url);
1109 |
1110 | Element root = connectAndParse(url);
1111 | for (Object obj : root.getChildren("address")) {
1112 | Element codeElement = (Element) obj;
1113 | Address address = new Address();
1114 | address.setStreet(codeElement.getChildText("street"));
1115 | address.setStreetNumber(codeElement.getChildText("houseNumber"));
1116 |
1117 | address.setPostalCode(codeElement.getChildText("postalcode"));
1118 | address.setPlaceName(codeElement.getChildText("locality"));
1119 | address.setCountryCode(codeElement.getChildText("countryCode"));
1120 |
1121 | address.setLatitude(Double.parseDouble(codeElement
1122 | .getChildText("lat")));
1123 | address.setLongitude(Double.parseDouble(codeElement
1124 | .getChildText("lng")));
1125 |
1126 | address.setAdminName1(codeElement.getChildText("adminName1"));
1127 | address.setAdminCode1(codeElement.getChildText("adminCode1"));
1128 | address.setAdminName2(codeElement.getChildText("adminName2"));
1129 | address.setAdminCode2(codeElement.getChildText("adminCode2"));
1130 | address.setAdminName3(codeElement.getChildText("adminName3"));
1131 | address.setAdminCode3(codeElement.getChildText("adminCode3"));
1132 |
1133 | return address;
1134 | }
1135 |
1136 | return null;
1137 | }
1138 | /**
1139 | * convenience method for {@link #search(ToponymSearchCriteria)}
1140 | *
1141 | * @see search
1142 | * web service documentation
1143 | *
1144 | * @param q
1145 | * @param countryCode
1146 | * @param name
1147 | * @param featureCodes
1148 | * @param startRow
1149 | * @return
1150 | * @throws Exception
1151 | */
1152 | public static ToponymSearchResult search(String q, String countryCode,
1153 | String name, String[] featureCodes, int startRow) throws Exception {
1154 | return search(q, countryCode, name, featureCodes, startRow, null, null,
1155 | null);
1156 | }
1157 |
1158 | /**
1159 | * convenience method for {@link #search(ToponymSearchCriteria)}
1160 | *
1161 | * The string fields will be transparently utf8 encoded within the call.
1162 | *
1163 | * @see search
1164 | * web service documentation
1165 | *
1166 | * @param q
1167 | * search over all fields
1168 | * @param countryCode
1169 | * @param name
1170 | * search over name only
1171 | * @param featureCodes
1172 | * @param startRow
1173 | * @param language
1174 | * @param style
1175 | * @param exactName
1176 | * @return
1177 | * @throws Exception
1178 | */
1179 | public static ToponymSearchResult search(String q, String countryCode,
1180 | String name, String[] featureCodes, int startRow, String language,
1181 | Style style, String exactName) throws Exception {
1182 | ToponymSearchCriteria searchCriteria = new ToponymSearchCriteria();
1183 | searchCriteria.setQ(q);
1184 | searchCriteria.setCountryCode(countryCode);
1185 | searchCriteria.setName(name);
1186 | searchCriteria.setFeatureCodes(featureCodes);
1187 | searchCriteria.setStartRow(startRow);
1188 | searchCriteria.setLanguage(language);
1189 | searchCriteria.setStyle(style);
1190 | searchCriteria.setNameEquals(exactName);
1191 | return search(searchCriteria);
1192 | }
1193 |
1194 | /**
1195 | * full text search on the GeoNames database.
1196 | *
1197 | * This service gets the number of toponyms defined by the 'maxRows'
1198 | * parameter. The parameter 'style' determines which fields are returned by
1199 | * the service.
1200 | *
1201 | * @see search
1202 | * web service documentation
1203 | *
1204 | *
1205 | *
1206 | *
1207 | * ToponymSearchCriteria searchCriteria = new ToponymSearchCriteria();
1208 | * searchCriteria.setQ("zürich");
1209 | * ToponymSearchResult searchResult = WebService.search(searchCriteria);
1210 | * for (Toponym toponym : searchResult.toponyms) {
1211 | * System.out.println(toponym.getName() + " " + toponym.getCountryName());
1212 | * }
1213 | *
1214 | *
1215 | *
1216 | * @param searchCriteria
1217 | * @return
1218 | * @throws Exception
1219 | */
1220 | public static ToponymSearchResult search(
1221 | ToponymSearchCriteria searchCriteria) throws Exception {
1222 | ToponymSearchResult searchResult = new ToponymSearchResult();
1223 |
1224 | String url = "/search?";
1225 |
1226 | if (searchCriteria.getQ() != null) {
1227 | url = url + "q=" + URLEncoder.encode(searchCriteria.getQ(), "UTF8");
1228 | }
1229 | if (searchCriteria.getNameEquals() != null) {
1230 | url = url + "&name_equals="
1231 | + URLEncoder.encode(searchCriteria.getNameEquals(), "UTF8");
1232 | }
1233 | if (searchCriteria.getNameStartsWith() != null) {
1234 | url = url
1235 | + "&name_startsWith="
1236 | + URLEncoder.encode(searchCriteria.getNameStartsWith(),
1237 | "UTF8");
1238 | }
1239 |
1240 | if (searchCriteria.getName() != null) {
1241 | url = url + "&name="
1242 | + URLEncoder.encode(searchCriteria.getName(), "UTF8");
1243 | }
1244 |
1245 | if (searchCriteria.getTag() != null) {
1246 | url = url + "&tag="
1247 | + URLEncoder.encode(searchCriteria.getTag(), "UTF8");
1248 | }
1249 |
1250 | if (searchCriteria.getCountryCode() != null) {
1251 | url = url + "&country=" + searchCriteria.getCountryCode();
1252 | }
1253 | if (searchCriteria.getCountryCodes() != null) {
1254 | for (String countryCode : searchCriteria.getCountryCodes()) {
1255 | url = url + "&country=" + countryCode;
1256 | }
1257 | }
1258 | if (searchCriteria.getCountryBias() != null) {
1259 | if (!url.endsWith("&")) {
1260 | url = url + "&";
1261 | }
1262 | url = url + "countryBias=" + searchCriteria.getCountryBias();
1263 | }
1264 | if (searchCriteria.getContinentCode() != null) {
1265 | url = url + "&continentCode=" + searchCriteria.getContinentCode();
1266 | }
1267 |
1268 | if (searchCriteria.getAdminCode1() != null) {
1269 | url = url + "&adminCode1="
1270 | + URLEncoder.encode(searchCriteria.getAdminCode1(), "UTF8");
1271 | }
1272 | if (searchCriteria.getAdminCode2() != null) {
1273 | url = url + "&adminCode2="
1274 | + URLEncoder.encode(searchCriteria.getAdminCode2(), "UTF8");
1275 | }
1276 | if (searchCriteria.getAdminCode3() != null) {
1277 | url = url + "&adminCode3="
1278 | + URLEncoder.encode(searchCriteria.getAdminCode3(), "UTF8");
1279 | }
1280 | if (searchCriteria.getAdminCode4() != null) {
1281 | url = url + "&adminCode4="
1282 | + URLEncoder.encode(searchCriteria.getAdminCode4(), "UTF8");
1283 | }
1284 |
1285 | if (searchCriteria.getLanguage() != null) {
1286 | url = url + "&lang=" + searchCriteria.getLanguage();
1287 | }
1288 |
1289 | if (searchCriteria.getFeatureClass() != null) {
1290 | url = url + "&featureClass=" + searchCriteria.getFeatureClass();
1291 | }
1292 |
1293 | if (searchCriteria.getFeatureCodes() != null) {
1294 | for (String featureCode : searchCriteria.getFeatureCodes()) {
1295 | url = url + "&fcode=" + featureCode;
1296 | }
1297 | }
1298 | if (searchCriteria.getMaxRows() > 0) {
1299 | url = url + "&maxRows=" + searchCriteria.getMaxRows();
1300 | }
1301 | if (searchCriteria.getStartRow() > 0) {
1302 | url = url + "&startRow=" + searchCriteria.getStartRow();
1303 | }
1304 | if (searchCriteria.getFuzzy() != 1.0) {
1305 | url = url + "&fuzzy=" + searchCriteria.getFuzzy();
1306 | }
1307 |
1308 | if (searchCriteria.getBoundingBox() != null) {
1309 | url = url + "&east=" + searchCriteria.getBoundingBox().getEast();
1310 | url = url + "&west=" + searchCriteria.getBoundingBox().getWest();
1311 | url = url + "&north=" + searchCriteria.getBoundingBox().getNorth();
1312 | url = url + "&south=" + searchCriteria.getBoundingBox().getSouth();
1313 | }
1314 |
1315 | if (searchCriteria.getStyle() != null) {
1316 | url = url + "&style=" + searchCriteria.getStyle();
1317 | } else {
1318 | url = addDefaultStyle(url);
1319 | }
1320 | url = addUserName(url);
1321 |
1322 | Element root = connectAndParse(url);
1323 | searchResult.totalResultsCount = Integer.parseInt(root
1324 | .getChildText("totalResultsCount"));
1325 | searchResult.setStyle(Style.valueOf(root.getAttributeValue("style")));
1326 |
1327 | for (Object obj : root.getChildren("geoname")) {
1328 | Element toponymElement = (Element) obj;
1329 | Toponym toponym = getToponymFromElement(toponymElement);
1330 | toponym.setStyle(searchResult.getStyle());
1331 | searchResult.toponyms.add(toponym);
1332 | }
1333 |
1334 | return searchResult;
1335 | }
1336 |
1337 | /**
1338 | * returns the children in the administrative hierarchy of a toponym. With
1339 | * default maxRows.
1340 | *
1341 | * @param geonameId
1342 | * @param language
1343 | * @param style
1344 | * @return
1345 | * @throws Exception
1346 | */
1347 | public static ToponymSearchResult children(int geonameId, String language,
1348 | Style style) throws Exception {
1349 | return children(geonameId, language, style, 0);
1350 | }
1351 |
1352 | /**
1353 | *
1354 | * @param geonameId
1355 | * @param language
1356 | * @param style
1357 | * @param maxRows
1358 | * @return
1359 | * @throws Exception
1360 | */
1361 | public static ToponymSearchResult children(int geonameId, String language,
1362 | Style style, int maxRows) throws Exception {
1363 |
1364 | ToponymSearchResult searchResult = new ToponymSearchResult();
1365 |
1366 | String url = "/children?";
1367 |
1368 | url = url + "geonameId=" + geonameId;
1369 |
1370 | if (language != null) {
1371 | url = url + "&lang=" + language;
1372 | }
1373 | if (maxRows != 0) {
1374 | url += "&maxRows=" + maxRows;
1375 | }
1376 |
1377 | if (style != null) {
1378 | url = url + "&style=" + style;
1379 | } else {
1380 | url = addDefaultStyle(url);
1381 | }
1382 | url = addUserName(url);
1383 |
1384 | Element root = connectAndParse(url);
1385 | searchResult.totalResultsCount = Integer.parseInt(root
1386 | .getChildText("totalResultsCount"));
1387 | searchResult.setStyle(Style.valueOf(root.getAttributeValue("style")));
1388 |
1389 | for (Object obj : root.getChildren("geoname")) {
1390 | Element toponymElement = (Element) obj;
1391 | Toponym toponym = getToponymFromElement(toponymElement);
1392 | searchResult.toponyms.add(toponym);
1393 | }
1394 |
1395 | return searchResult;
1396 | }
1397 |
1398 | /**
1399 | * returns the neighbours of a toponym.
1400 | *
1401 | * @param geonameId
1402 | * @param language
1403 | * @param style
1404 | * @return
1405 | * @throws Exception
1406 | */
1407 | public static ToponymSearchResult neighbours(int geonameId,
1408 | String language, Style style) throws Exception {
1409 | ToponymSearchResult searchResult = new ToponymSearchResult();
1410 |
1411 | String url = "/neighbours?";
1412 |
1413 | url = url + "geonameId=" + geonameId;
1414 |
1415 | if (language != null) {
1416 | url = url + "&lang=" + language;
1417 | }
1418 |
1419 | if (style != null) {
1420 | url = url + "&style=" + style;
1421 | } else {
1422 | url = addDefaultStyle(url);
1423 | }
1424 | url = addUserName(url);
1425 |
1426 | Element root = connectAndParse(url);
1427 | searchResult.totalResultsCount = Integer.parseInt(root
1428 | .getChildText("totalResultsCount"));
1429 | searchResult.setStyle(Style.valueOf(root.getAttributeValue("style")));
1430 |
1431 | for (Object obj : root.getChildren("geoname")) {
1432 | Element toponymElement = (Element) obj;
1433 | Toponym toponym = getToponymFromElement(toponymElement);
1434 | searchResult.toponyms.add(toponym);
1435 | }
1436 |
1437 | return searchResult;
1438 | }
1439 |
1440 | /**
1441 | * returns the hierarchy for a geonameId
1442 | *
1443 | * @see Hierarchy
1445 | * service description
1446 | *
1447 | * @param geonameId
1448 | * @param language
1449 | * @param style
1450 | * @return
1451 | * @throws Exception
1452 | */
1453 | public static List hierarchy(int geonameId, String language,
1454 | Style style) throws Exception {
1455 |
1456 | String url = "/hierarchy?";
1457 |
1458 | url = url + "geonameId=" + geonameId;
1459 |
1460 | if (language != null) {
1461 | url = url + "&lang=" + language;
1462 | }
1463 |
1464 | if (style != null) {
1465 | url = url + "&style=" + style;
1466 | } else {
1467 | url = addDefaultStyle(url);
1468 | }
1469 | url = addUserName(url);
1470 |
1471 | Element root = connectAndParse(url);
1472 | List toponyms = new ArrayList();
1473 | for (Object obj : root.getChildren("geoname")) {
1474 | Element toponymElement = (Element) obj;
1475 | Toponym toponym = getToponymFromElement(toponymElement);
1476 | toponyms.add(toponym);
1477 | }
1478 |
1479 | return toponyms;
1480 | }
1481 |
1482 | public static void saveTags(String[] tags, Toponym toponym,
1483 | String username, String password) throws Exception {
1484 | if (toponym.getGeoNameId() == 0) {
1485 | throw new Error("no geonameid specified");
1486 | }
1487 |
1488 | // FIXME proper url
1489 | String url = "/servlet/geonames?srv=61";
1490 |
1491 | url = url + "&geonameId=" + toponym.getGeoNameId();
1492 | url = addUserName(url);
1493 |
1494 | StringBuilder tagsCommaseparated = new StringBuilder();
1495 | for (String tag : tags) {
1496 | tagsCommaseparated.append(tag + ",");
1497 | }
1498 | url = url + "&tag=" + tagsCommaseparated;
1499 |
1500 | Element root = connectAndParse(url);
1501 | }
1502 |
1503 | /**
1504 | * full text search on geolocated wikipedia articles.
1505 | *
1506 | * @param q
1507 | * @param language
1508 | * @return
1509 | * @throws Exception
1510 | */
1511 | public static List wikipediaSearch(String q,
1512 | String language) throws Exception {
1513 | List articles = new ArrayList();
1514 |
1515 | String url = "/wikipediaSearch?";
1516 |
1517 | url = url + "q=" + URLEncoder.encode(q, "UTF8");
1518 |
1519 | if (language != null) {
1520 | url = url + "&lang=" + language;
1521 | }
1522 | url = addUserName(url);
1523 |
1524 | Element root = connectAndParse(url);
1525 | for (Object obj : root.getChildren("entry")) {
1526 | Element wikipediaArticleElement = (Element) obj;
1527 | WikipediaArticle wikipediaArticle = getWikipediaArticleFromElement(wikipediaArticleElement);
1528 | articles.add(wikipediaArticle);
1529 | }
1530 |
1531 | return articles;
1532 | }
1533 |
1534 | /**
1535 | * full text search on geolocated wikipedia articles.
1536 | *
1537 | * @param title
1538 | * @param language
1539 | * @return
1540 | * @throws Exception
1541 | */
1542 | public static List wikipediaSearchForTitle(String title,
1543 | String language) throws Exception {
1544 | List articles = new ArrayList();
1545 |
1546 | String url = "/wikipediaSearch?";
1547 |
1548 | url = url + "title=" + URLEncoder.encode(title, "UTF8");
1549 |
1550 | if (language != null) {
1551 | url = url + "&lang=" + language;
1552 | }
1553 | url = addUserName(url);
1554 |
1555 | Element root = connectAndParse(url);
1556 | for (Object obj : root.getChildren("entry")) {
1557 | Element wikipediaArticleElement = (Element) obj;
1558 | WikipediaArticle wikipediaArticle = getWikipediaArticleFromElement(wikipediaArticleElement);
1559 | articles.add(wikipediaArticle);
1560 | }
1561 |
1562 | return articles;
1563 | }
1564 |
1565 | public static List findNearbyWikipedia(double latitude,
1566 | double longitude, String language) throws Exception {
1567 | return findNearbyWikipedia(latitude, longitude, 0, language, 0);
1568 | }
1569 |
1570 | /* Overload function to allow backward compatibility */
1571 | /**
1572 | * Based on the following inform: Webservice Type : REST
1573 | * api.geonames.org/findNearbyWikipedia? Parameters : lang : language code
1574 | * (around 240 languages) (default = en) lat,lng, radius (in km), maxRows
1575 | * (default = 5) Example:
1576 | * http://api.geonames.org/findNearbyWikipedia?lat=47&lng=9
1577 | *
1578 | * @param: latitude
1579 | * @param: longitude
1580 | * @param: radius
1581 | * @param: language
1582 | * @param: maxRows
1583 | * @return: list of wikipedia articles
1584 | * @throws: Exception
1585 | */
1586 | public static List findNearbyWikipedia(double latitude,
1587 | double longitude, double radius, String language, int maxRows)
1588 | throws Exception {
1589 |
1590 | List articles = new ArrayList();
1591 |
1592 | String url = "/findNearbyWikipedia?";
1593 |
1594 | url = url + "lat=" + latitude;
1595 | url = url + "&lng=" + longitude;
1596 | if (radius > 0) {
1597 | url = url + "&radius=" + radius;
1598 | }
1599 | if (maxRows > 0) {
1600 | url = url + "&maxRows=" + maxRows;
1601 | }
1602 |
1603 | if (language != null) {
1604 | url = url + "&lang=" + language;
1605 | }
1606 | url = addUserName(url);
1607 |
1608 | Element root = connectAndParse(url);
1609 | for (Object obj : root.getChildren("entry")) {
1610 | Element wikipediaArticleElement = (Element) obj;
1611 | WikipediaArticle wikipediaArticle = getWikipediaArticleFromElement(wikipediaArticleElement);
1612 | articles.add(wikipediaArticle);
1613 | }
1614 |
1615 | return articles;
1616 | }
1617 |
1618 | /**
1619 | * GTOPO30 is a global digital elevation model (DEM) with a horizontal grid
1620 | * spacing of 30 arc seconds (approximately 1 kilometer). GTOPO30 was
1621 | * derived from several raster and vector sources of topographic
1622 | * information.
1623 | *
1624 | * @param latitude
1625 | * @param longitude
1626 | * @return a single number giving the elevation in meters according to
1627 | * gtopo30, ocean areas have been masked as "no data" and have been
1628 | * assigned a value of -9999
1629 | * @throws IOException
1630 | * @throws GeoNamesException
1631 | */
1632 | public static int gtopo30(double latitude, double longitude)
1633 | throws IOException, GeoNamesException {
1634 | String url = "/gtopo30?lat=" + latitude + "&lng=" + longitude;
1635 | url = addUserName(url);
1636 | BufferedReader in = new BufferedReader(new InputStreamReader(
1637 | connect(url)));
1638 | String gtopo30 = in.readLine();
1639 | in.close();
1640 | checkException(gtopo30);
1641 | return Integer.parseInt(gtopo30);
1642 | }
1643 |
1644 | /**
1645 | * Shuttle Radar Topography Mission (SRTM) elevation data. SRTM consisted of
1646 | * a specially modified radar system that flew onboard the Space Shuttle
1647 | * Endeavour during an 11-day mission in February of 2000. The dataset
1648 | * covers land areas between 60 degrees north and 56 degrees south. This web
1649 | * service is using SRTM3 data with data points located every 3-arc-second
1650 | * (approximately 90 meters) on a latitude/longitude grid.
1651 | *
1652 | * @param latitude
1653 | * @param longitude
1654 | * @return elevation or -32768 if unknown
1655 | * @throws IOException
1656 | * @throws GeoNamesException
1657 | */
1658 | public static int srtm3(double latitude, double longitude)
1659 | throws IOException, GeoNamesException {
1660 | String url = "/srtm3?lat=" + latitude + "&lng=" + longitude;
1661 | url = addUserName(url);
1662 | BufferedReader in = new BufferedReader(new InputStreamReader(
1663 | connect(url)));
1664 | String srtm3 = in.readLine();
1665 | in.close();
1666 | checkException(srtm3);
1667 | return Integer.parseInt(srtm3);
1668 | }
1669 |
1670 | public static int[] srtm3(double[] latitude, double[] longitude)
1671 | throws IOException {
1672 | if (latitude.length != longitude.length) {
1673 | throw new Error("number of lats and longs must be equal");
1674 | }
1675 | int[] elevation = new int[latitude.length];
1676 | String lats = "";
1677 | String lngs = "";
1678 | for (int i = 0; i < elevation.length; i++) {
1679 | lats += latitude[i] + ",";
1680 | lngs += longitude[i] + ",";
1681 | }
1682 | String url = "/srtm3?lats=" + lats + "&lngs=" + lngs;
1683 | url = addUserName(url);
1684 | BufferedReader in = new BufferedReader(new InputStreamReader(
1685 | connect(url)));
1686 | for (int i = 0; i < elevation.length; i++) {
1687 | String srtm3 = in.readLine();
1688 | elevation[i] = Integer.parseInt(srtm3);
1689 | }
1690 | in.close();
1691 | return elevation;
1692 | }
1693 |
1694 | public static int astergdem(double latitude, double longitude)
1695 | throws IOException, GeoNamesException {
1696 | String url = "/astergdem?lat=" + latitude + "&lng=" + longitude;
1697 | url = addUserName(url);
1698 | BufferedReader in = new BufferedReader(new InputStreamReader(
1699 | connect(url)));
1700 | String astergdem = in.readLine();
1701 | in.close();
1702 | checkException(astergdem);
1703 | return Integer.parseInt(astergdem);
1704 | }
1705 |
1706 | public static int[] astergdem(double[] latitude, double[] longitude)
1707 | throws IOException {
1708 | if (latitude.length != longitude.length) {
1709 | throw new Error("number of lats and longs must be equal");
1710 | }
1711 | int[] elevation = new int[latitude.length];
1712 | String lats = "";
1713 | String lngs = "";
1714 | for (int i = 0; i < elevation.length; i++) {
1715 | lats += latitude[i] + ",";
1716 | lngs += longitude[i] + ",";
1717 | }
1718 | String url = "/astergdem?lats=" + lats + "&lngs=" + lngs;
1719 | url = addUserName(url);
1720 | BufferedReader in = new BufferedReader(new InputStreamReader(
1721 | connect(url)));
1722 | for (int i = 0; i < elevation.length; i++) {
1723 | String astergdem = in.readLine();
1724 | elevation[i] = Integer.parseInt(astergdem);
1725 | }
1726 | in.close();
1727 | return elevation;
1728 | }
1729 |
1730 | /**
1731 | * The iso country code of any given point. It is calling
1732 | * {@link #countryCode(double, double, double)} with radius=0.0
1733 | *
1734 | * @param latitude
1735 | * @param longitude
1736 | * @return
1737 | * @throws IOException
1738 | * @throws GeoNamesException
1739 | */
1740 | public static String countryCode(double latitude, double longitude)
1741 | throws IOException, GeoNamesException {
1742 | return countryCode(latitude, longitude, 0);
1743 | }
1744 |
1745 | /**
1746 | * The iso country code of any given point with radius for coastal areas.
1747 | *
1748 | * @param latitude
1749 | * @param longitude
1750 | * @param radius
1751 | *
1752 | * @return iso country code for the given latitude/longitude
1753 | * @throws IOException
1754 | * @throws GeoNamesException
1755 | */
1756 | public static String countryCode(double latitude, double longitude,
1757 | double radius) throws IOException, GeoNamesException {
1758 | String url = "/countryCode?lat=" + latitude + "&lng=" + longitude;
1759 | if (radius != 0) {
1760 | url += "&radius=" + radius;
1761 | }
1762 | url = addUserName(url);
1763 | BufferedReader in = new BufferedReader(new InputStreamReader(
1764 | connect(url)));
1765 | String cc = in.readLine();
1766 | in.close();
1767 | if (cc != null && cc.length() == 2) {
1768 | return cc;
1769 | }
1770 | if (cc == null || cc.length() == 0) {
1771 | // nothing found return null
1772 | return null;
1773 | }
1774 | // check whether we can parse an exception and throw it if we can
1775 | checkException(cc);
1776 | // something else was wrong, through generic exception
1777 | throw new GeoNamesException("unhandled exception");
1778 | }
1779 |
1780 | /**
1781 | * get the timezone for a given location
1782 | *
1783 | * @param latitude
1784 | * @param longitude
1785 | * @return timezone at the given location
1786 | * @throws IOException
1787 | * @throws Exception
1788 | */
1789 | public static Timezone timezone(double latitude, double longitude)
1790 | throws IOException, Exception {
1791 |
1792 | String url = "/timezone?";
1793 | double radius = 0;
1794 |
1795 | url = url + "&lat=" + latitude;
1796 | url = url + "&lng=" + longitude;
1797 | if (radius > 0) {
1798 | url = url + "&radius=" + radius;
1799 | }
1800 | url = addUserName(url);
1801 |
1802 | Element root = connectAndParse(url);
1803 | for (Object obj : root.getChildren("timezone")) {
1804 | Element codeElement = (Element) obj;
1805 | Timezone timezone = new Timezone();
1806 | timezone.setTimezoneId(codeElement.getChildText("timezoneId"));
1807 | timezone.setCountryCode(codeElement.getChildText("countryCode"));
1808 |
1809 | if (codeElement.getChildText("time") != null) {
1810 | String minuteDateFmt = "yyyy-MM-dd HH:mm";
1811 | SimpleDateFormat df = null;
1812 | if (codeElement.getChildText("time").length() == minuteDateFmt
1813 | .length()) {
1814 | df = new SimpleDateFormat(minuteDateFmt);
1815 | } else {
1816 | df = new SimpleDateFormat(DATEFMT);
1817 | }
1818 | timezone.setTime(df.parse(codeElement.getChildText("time")));
1819 | if (codeElement.getChildText("sunrise") != null) {
1820 | timezone.setSunrise(df.parse(codeElement
1821 | .getChildText("sunrise")));
1822 | }
1823 | if (codeElement.getChildText("sunset") != null) {
1824 | timezone.setSunset(df.parse(codeElement
1825 | .getChildText("sunset")));
1826 | }
1827 | timezone.setGmtOffset(Double.parseDouble(codeElement
1828 | .getChildText("gmtOffset")));
1829 | timezone.setDstOffset(Double.parseDouble(codeElement
1830 | .getChildText("dstOffset")));
1831 | }
1832 | return timezone;
1833 | }
1834 |
1835 | return null;
1836 | }
1837 |
1838 | //FIXME implement and test
1839 | public static String ocean(double latitude, double longitude)
1840 | throws IOException, Exception {
1841 |
1842 | String url = "/ocean?";
1843 | double radius = 0;
1844 |
1845 | url = url + "&lat=" + latitude;
1846 | url = url + "&lng=" + longitude;
1847 | if (radius > 0) {
1848 | url = url + "&radius=" + radius;
1849 | }
1850 | url = addUserName(url);
1851 |
1852 | Element root = connectAndParse(url);
1853 | for (Object obj : root.getChildren("ocean")) {
1854 | Element oceanElement = (Element) obj;
1855 | if (oceanElement != null) {
1856 | return oceanElement.getChildText("name");
1857 | }
1858 | }
1859 |
1860 | return null;
1861 | }
1862 |
1863 | /**
1864 | *
1865 | * @param latitude
1866 | * @param longitude
1867 | * @return
1868 | * @throws IOException
1869 | * @throws Exception
1870 | */
1871 | public static WeatherObservation findNearByWeather(double latitude,
1872 | double longitude) throws IOException, Exception {
1873 |
1874 | String url = "/findNearByWeatherXML?";
1875 |
1876 | url = url + "&lat=" + latitude;
1877 | url = url + "&lng=" + longitude;
1878 | url = addUserName(url);
1879 |
1880 | Element root = connectAndParse(url);
1881 | for (Object obj : root.getChildren("observation")) {
1882 | Element weatherObservationElement = (Element) obj;
1883 | WeatherObservation weatherObservation = getWeatherObservationFromElement(weatherObservationElement);
1884 | return weatherObservation;
1885 | }
1886 |
1887 | return null;
1888 | }
1889 |
1890 | public static WeatherObservation weatherIcao(String icaoCode)
1891 | throws IOException, Exception {
1892 |
1893 | String url = "/weatherIcaoXML?";
1894 |
1895 | url = url + "&ICAO=" + icaoCode;
1896 | url = addUserName(url);
1897 |
1898 | Element root = connectAndParse(url);
1899 | for (Object obj : root.getChildren("observation")) {
1900 | Element weatherObservationElement = (Element) obj;
1901 | WeatherObservation weatherObservation = getWeatherObservationFromElement(weatherObservationElement);
1902 | return weatherObservation;
1903 | }
1904 |
1905 | return null;
1906 | }
1907 |
1908 | /**
1909 | * @return the geoNamesServer, default is http://api.geonames.org
1910 | */
1911 | public static String getGeoNamesServer() {
1912 | return geoNamesServer;
1913 | }
1914 |
1915 | /**
1916 | * @return the geoNamesServerFailover
1917 | */
1918 | public static String getGeoNamesServerFailover() {
1919 | return geoNamesServerFailover;
1920 | }
1921 |
1922 | /**
1923 | * sets the server name for the GeoNames server to be used for the requests.
1924 | * Default is api.geonames.org
1925 | *
1926 | * @param geoNamesServer
1927 | * the geonamesServer to set
1928 | */
1929 | public static void setGeoNamesServer(String pGeoNamesServer) {
1930 | if (pGeoNamesServer == null) {
1931 | throw new Error();
1932 | }
1933 | pGeoNamesServer = pGeoNamesServer.trim().toLowerCase();
1934 | // add default http protocol if it is missing
1935 | if (!pGeoNamesServer.startsWith("http://")
1936 | && !pGeoNamesServer.startsWith("https://")) {
1937 | pGeoNamesServer = "http://" + pGeoNamesServer;
1938 | }
1939 | WebService.geoNamesServer = pGeoNamesServer;
1940 | }
1941 |
1942 | /**
1943 | * sets the default failover server for requests in case the main server is
1944 | * not accessible. Default is api.geonames.org
1945 | * The failover server is only called if it is different from the main
1946 | * server.
1947 | * The failover server is used for commercial GeoNames web service users.
1948 | *
1949 | * @param geoNamesServerFailover
1950 | * the geoNamesServerFailover to set
1951 | */
1952 | public static void setGeoNamesServerFailover(String geoNamesServerFailover) {
1953 | if (geoNamesServerFailover != null) {
1954 | geoNamesServerFailover = geoNamesServerFailover.trim()
1955 | .toLowerCase();
1956 | if (!geoNamesServerFailover.startsWith("http://")
1957 | && !geoNamesServerFailover.startsWith("https://")) {
1958 | geoNamesServerFailover = "http://" + geoNamesServerFailover;
1959 | }
1960 | }
1961 | WebService.geoNamesServerFailover = geoNamesServerFailover;
1962 | }
1963 |
1964 | /**
1965 | * @return the proxy
1966 | */
1967 | public static Proxy getProxy() {
1968 | return proxy;
1969 | }
1970 |
1971 | /**
1972 | * @param proxy
1973 | * the proxy to set
1974 | *
1975 | * If you are behind a proxy and cannot change the java system
1976 | * properties, you can use this method to set a proxy. You define
1977 | * it like this:
1978 | *
1979 | *
1980 | *
1981 | * java.net.SocketAddress sa = new java.net.InetSocketAddress("myproxyserver", 8080);
1982 | * java.net.Proxy proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, sa);
1983 | *
1984 | *
1985 | */
1986 | public static void setProxy(Proxy proxy) {
1987 | WebService.proxy = proxy;
1988 | }
1989 |
1990 | /**
1991 | * @return the userName
1992 | */
1993 | public static String getUserName() {
1994 | return userName;
1995 | }
1996 |
1997 | /**
1998 | * Sets the user name to be used for the requests. Needed to access the
1999 | * commercial GeoNames web services.
2000 | *
2001 | * @param userName
2002 | * the userName to set
2003 | */
2004 | public static void setUserName(String userName) {
2005 | WebService.userName = userName;
2006 | }
2007 |
2008 | /**
2009 | * @return the token
2010 | */
2011 | public static String getToken() {
2012 | return token;
2013 | }
2014 |
2015 | /**
2016 | * sets the token to be used to authenticate the requests. This is an
2017 | * optional parameter for the commercial version of the GeoNames web
2018 | * services.
2019 | *
2020 | * @param token
2021 | * the token to set
2022 | */
2023 | public static void setToken(String token) {
2024 | WebService.token = token;
2025 | }
2026 |
2027 | /**
2028 | * @return the defaultStyle
2029 | */
2030 | public static Style getDefaultStyle() {
2031 | return defaultStyle;
2032 | }
2033 |
2034 | /**
2035 | * @param defaultStyle
2036 | * the defaultStyle to set
2037 | */
2038 | public static void setDefaultStyle(Style defaultStyle) {
2039 | WebService.defaultStyle = defaultStyle;
2040 | }
2041 |
2042 | /**
2043 | * @return the readTimeOut
2044 | */
2045 | public static int getReadTimeOut() {
2046 | return readTimeOut;
2047 | }
2048 |
2049 | /**
2050 | * @param readTimeOut
2051 | * the readTimeOut to set
2052 | */
2053 | public static void setReadTimeOut(int readTimeOut) {
2054 | WebService.readTimeOut = readTimeOut;
2055 | }
2056 |
2057 | /**
2058 | * @return the connectTimeOut
2059 | */
2060 | public static int getConnectTimeOut() {
2061 | return connectTimeOut;
2062 | }
2063 |
2064 | /**
2065 | * @param connectTimeOut
2066 | * the connectTimeOut to set
2067 | */
2068 | public static void setConnectTimeOut(int connectTimeOut) {
2069 | WebService.connectTimeOut = connectTimeOut;
2070 | }
2071 |
2072 | }
2073 |
--------------------------------------------------------------------------------