└── org └── geonames ├── utils ├── package.html ├── DistanceOrder.java ├── Bearing.java └── Distance.java ├── Style.java ├── InvalidParameterException.java ├── InsufficientStyleException.java ├── package.html ├── GeoNamesException.java ├── FeatureClass.java ├── Address.java ├── ToponymSearchResult.java ├── BoundingBox.java ├── Intersection.java ├── Timezone.java ├── StreetSegment.java ├── PostalCode.java ├── WikipediaArticle.java ├── WeatherObservation.java ├── PostalCodeSearchCriteria.java ├── ToponymSearchCriteria.java ├── wikipedia └── TextSummaryExtractor.java ├── Toponym.java └── WebService.java /org/geonames/utils/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Utility classes for GeoNames 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /org/geonames/Style.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 | 18 | package org.geonames; 19 | 20 | /** 21 | * Enumeration for style parameter specifying the verbosity of geonames web 22 | * services 23 | * 24 | * @author marc@geonames 25 | * 26 | */ 27 | public enum Style { 28 | SHORT, MEDIUM, LONG, FULL 29 | } -------------------------------------------------------------------------------- /org/geonames/InvalidParameterException.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 | * is thrown when the search criteria is initialized with obviously invalid parameters, 21 | * such as an invalid country code. 22 | * 23 | * @author marc 24 | * 25 | */ 26 | public class InvalidParameterException extends GeoNamesException { 27 | 28 | public InvalidParameterException(String msg) { 29 | super(msg); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /org/geonames/InsufficientStyleException.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 | * Is thrown when trying to access a field that has not been set as the style 21 | * for the request was not sufficiently verbose to return this information. 22 | * 23 | * @author marc 24 | * 25 | */ 26 | public class InsufficientStyleException extends GeoNamesException { 27 | public InsufficientStyleException(String msg) { 28 | super(msg); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /org/geonames/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | GeoNames Java API main classes. 11 | 12 |

Webservice Code Examples

13 | 14 |

geonames full text search

15 | 16 | 17 | Code Example : 18 |
   
19 |   ToponymSearchCriteria searchCriteria = new ToponymSearchCriteria();
20 |   searchCriteria.setQ("zurich");
21 |   ToponymSearchResult searchResult = WebService.search(searchCriteria);
22 |   for (Toponym toponym : searchResult.toponyms) {
23 |      System.out.println(toponym.getName()+" "+ toponym.getCountryName());
24 |   }
25 | 
26 | 27 | 28 |


29 | 30 | 31 |

Reverse Geocoding - find next postal codes for given latitude and longitude

32 | 33 | 34 | Code Example : 35 |
   
36 |   PostalCodeSearchCriteria postalCodeSearchCriteria = new PostalCodeSearchCriteria();
37 |   postalCodeSearchCriteria.setLatitude(37.373636);
38 |   postalCodeSearchCriteria.setLongitude(-121.972146);
39 |   List postalCodes = WebService.findNearbyPostalCodes(postalCodeSearchCriteria);
40 | 
41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /org/geonames/utils/DistanceOrder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 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.utils; 18 | 19 | import java.util.Comparator; 20 | 21 | import org.geonames.WikipediaArticle; 22 | 23 | /** 24 | * @author marc 25 | * @since 16.02.2011 26 | * 27 | */ 28 | public class DistanceOrder implements Comparator { 29 | private double latitude; 30 | private double longitude; 31 | 32 | public DistanceOrder(double pLat, double pLng) { 33 | latitude = pLat; 34 | longitude = pLng; 35 | } 36 | 37 | public int compare(WikipediaArticle o1, WikipediaArticle o2) { 38 | double dist1 = dist(o1); 39 | double dist2 = dist(o2); 40 | return Double.compare(dist1, dist2); 41 | } 42 | 43 | private double dist(WikipediaArticle o) { 44 | return Distance.distanceKM(latitude, longitude, o.getLatitude(), o 45 | .getLongitude()); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /org/geonames/GeoNamesException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 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 | * @author marc 21 | * @since 20.01.2011 22 | * 23 | */ 24 | public class GeoNamesException extends Exception { 25 | 26 | private static final long serialVersionUID = 746586385626445380L; 27 | private String message; 28 | private int exceptionCode; 29 | 30 | public GeoNamesException(int exceptionCode, String msg) { 31 | super(msg); 32 | this.message = msg; 33 | this.exceptionCode = exceptionCode; 34 | } 35 | 36 | public GeoNamesException(String msg) { 37 | super(msg); 38 | this.message=msg; 39 | } 40 | 41 | /** 42 | * @return the message 43 | */ 44 | public String getMessage() { 45 | return message; 46 | } 47 | 48 | /** 49 | * @return the exceptionCode 50 | */ 51 | public int getExceptionCode() { 52 | return exceptionCode; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /org/geonames/FeatureClass.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 | * Enumeration for the GeoNames feature classes A,H,L,P,R,S,T,U,V 21 | * 22 | * @author marc 23 | * 24 | */ 25 | public enum FeatureClass { 26 | /** 27 | * Administrative Boundary Features 28 | */ 29 | A, 30 | /** 31 | * Hydrographic Features 32 | */ 33 | H, 34 | /** 35 | * Area Features 36 | */ 37 | L, 38 | /** 39 | * Populated Place Features 40 | */ 41 | P, 42 | /** 43 | * Road / Railroad Features 44 | */ 45 | R, 46 | /** 47 | * Spot Features 48 | */ 49 | S, 50 | /** 51 | * Hypsographic Features 52 | */ 53 | T, 54 | /** 55 | * Undersea Features 56 | */ 57 | U, 58 | /** 59 | * Vegetation Features 60 | */ 61 | V; 62 | 63 | public static FeatureClass fromValue(String value) { 64 | if (value == null || "".equals(value)) { 65 | return null; 66 | } 67 | return valueOf(value); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /org/geonames/Address.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 street address 21 | * 22 | * @author Mark Thomas 23 | * 24 | */ 25 | public class Address extends PostalCode { 26 | 27 | private String street; 28 | 29 | private String streetNumber; 30 | 31 | private String mtfcc; 32 | 33 | /** 34 | * @return the street 35 | */ 36 | public String getStreet() { 37 | return street; 38 | } 39 | 40 | /** 41 | * @param street 42 | * the street to set 43 | */ 44 | public void setStreet(String street) { 45 | this.street = street; 46 | } 47 | 48 | /** 49 | * @return the streetNumber 50 | */ 51 | public String getStreetNumber() { 52 | return streetNumber; 53 | } 54 | 55 | /** 56 | * @param streetNumber 57 | * the streetNumber to set 58 | */ 59 | public void setStreetNumber(String streetNumber) { 60 | this.streetNumber = streetNumber; 61 | } 62 | 63 | /** 64 | * @return the mtfcc 65 | */ 66 | public String getMtfcc() { 67 | return mtfcc; 68 | } 69 | 70 | /** 71 | * @param mtfcc 72 | * the mtfcc to set 73 | */ 74 | public void setMtfcc(String mtfcc) { 75 | this.mtfcc = mtfcc; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /org/geonames/utils/Bearing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2006 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.utils; 18 | 19 | import static java.lang.Math.atan2; 20 | import static java.lang.Math.cos; 21 | import static java.lang.Math.sin; 22 | import static java.lang.Math.toDegrees; 23 | import static java.lang.Math.toRadians; 24 | 25 | /** 26 | * compass bearing from the first point to the second point in degrees. 27 | * 28 | * @author Marc Wick 29 | */ 30 | public class Bearing { 31 | 32 | /** 33 | * Returns the direction from the first point to the second point in 34 | * degrees. The direction is the clockwise angle between the magnetic north 35 | * and the direction from point1 to point2 36 | * 37 | * @param lat1 38 | * @param lng1 39 | * @param lat2 40 | * @param lng2 41 | * @return 42 | */ 43 | // http://www.movable-type.co.uk/scripts/latlong.html 44 | public static double calculateBearing(double lat1, double lng1, 45 | double lat2, double lng2) { 46 | double dLon = toRadians(lng2 - lng1); 47 | lat1 = toRadians(lat1); 48 | lat2 = toRadians(lat2); 49 | double y = sin(dLon) * cos(lat2); 50 | double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon); 51 | double brng = toDegrees(atan2(y, x)); 52 | return (brng + 360) % 360; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /org/geonames/ToponymSearchResult.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 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * a toponym search result as returned by the geonames webservice. 24 | * 25 | * @author marc@geonames 26 | * 27 | */ 28 | public class ToponymSearchResult { 29 | 30 | List toponyms = new ArrayList(); 31 | 32 | int totalResultsCount; 33 | 34 | Style style; 35 | 36 | /** 37 | * @return Returns the toponyms. 38 | */ 39 | public List getToponyms() { 40 | return toponyms; 41 | } 42 | 43 | /** 44 | * @param toponyms 45 | * The toponyms to set. 46 | */ 47 | public void setToponyms(List toponyms) { 48 | this.toponyms = toponyms; 49 | } 50 | 51 | /** 52 | * @return Returns the totalResultsCount. 53 | */ 54 | public int getTotalResultsCount() { 55 | return totalResultsCount; 56 | } 57 | 58 | /** 59 | * @param totalResultsCount 60 | * The totalResultsCount to set. 61 | */ 62 | public void setTotalResultsCount(int totalResultsCount) { 63 | this.totalResultsCount = totalResultsCount; 64 | } 65 | 66 | /** 67 | * @return the style 68 | */ 69 | public Style getStyle() { 70 | return style; 71 | } 72 | 73 | /** 74 | * @param style the style to set 75 | */ 76 | public void setStyle(Style style) { 77 | this.style = style; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /org/geonames/BoundingBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 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 | /** 20 | * @author Marc Wick 21 | * @since 15.08.2012 22 | * 23 | */ 24 | public class BoundingBox { 25 | 26 | public BoundingBox(double west, double east, double south, double north) { 27 | setWest(west); 28 | setEast(east); 29 | setSouth(south); 30 | setNorth(north); 31 | } 32 | 33 | /** 34 | * @return the west 35 | */ 36 | public double getWest() { 37 | return west; 38 | } 39 | 40 | /** 41 | * @param west 42 | * the west to set 43 | */ 44 | public void setWest(double west) { 45 | this.west = west; 46 | } 47 | 48 | /** 49 | * @return the east 50 | */ 51 | public double getEast() { 52 | return east; 53 | } 54 | 55 | /** 56 | * @param east 57 | * the east to set 58 | */ 59 | public void setEast(double east) { 60 | this.east = east; 61 | } 62 | 63 | /** 64 | * @return the south 65 | */ 66 | public double getSouth() { 67 | return south; 68 | } 69 | 70 | /** 71 | * @param south 72 | * the south to set 73 | */ 74 | public void setSouth(double south) { 75 | this.south = south; 76 | } 77 | 78 | /** 79 | * @return the north 80 | */ 81 | public double getNorth() { 82 | return north; 83 | } 84 | 85 | /** 86 | * @param north 87 | * the north to set 88 | */ 89 | public void setNorth(double north) { 90 | this.north = north; 91 | } 92 | 93 | private double west; 94 | private double east; 95 | private double south; 96 | private double north; 97 | 98 | } 99 | -------------------------------------------------------------------------------- /org/geonames/Intersection.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 | * an intersection between two streets 21 | * 22 | * @author Mark Thomas 23 | * 24 | */ 25 | public class Intersection { 26 | private String street2; 27 | 28 | private Address address = new Address(); 29 | 30 | public double getDistance() { 31 | return address.getDistance(); 32 | } 33 | 34 | public void setDistance(double d) { 35 | address.setDistance(d); 36 | } 37 | 38 | public String getAdminCode1() { 39 | return address.getAdminCode1(); 40 | } 41 | 42 | public void setAdminCode1(String s) { 43 | address.setAdminCode1(s); 44 | } 45 | 46 | public String getAdminName1() { 47 | return address.getAdminName1(); 48 | } 49 | 50 | public void setAdminName1(String s) { 51 | address.setAdminName1(s); 52 | } 53 | 54 | public String getAdminName2() { 55 | return address.getAdminName2(); 56 | } 57 | 58 | public void setAdminName2(String s) { 59 | address.setAdminName2(s); 60 | } 61 | 62 | public String getCountryCode() { 63 | return address.getCountryCode(); 64 | } 65 | 66 | public void setCountryCode(String s) { 67 | address.setCountryCode(s); 68 | } 69 | 70 | public double getLatitude() { 71 | return address.getLatitude(); 72 | } 73 | 74 | public void setLatitude(double d) { 75 | address.setLatitude(d); 76 | } 77 | 78 | public double getLongitude() { 79 | return address.getLongitude(); 80 | } 81 | 82 | public void setLongitude(double d) { 83 | address.setLongitude(d); 84 | } 85 | 86 | public String getPlaceName() { 87 | return address.getPlaceName(); 88 | } 89 | 90 | public void setPlaceName(String s) { 91 | address.setPlaceName(s); 92 | } 93 | 94 | public String getPostalCode() { 95 | return address.getPostalCode(); 96 | } 97 | 98 | public void setPostalCode(String s) { 99 | address.setPostalCode(s); 100 | } 101 | 102 | public String getStreet1() { 103 | return address.getStreet(); 104 | } 105 | 106 | public void setStreet1(String s) { 107 | address.setStreet(s); 108 | } 109 | 110 | public String getStreet2() { 111 | return street2; 112 | } 113 | 114 | public void setStreet2(String street2) { 115 | this.street2 = street2; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /org/geonames/utils/Distance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2006 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.utils; 18 | 19 | /** 20 | * Distance calculations. 21 | * 22 | * @author marc@geonames 23 | * 24 | */ 25 | public class Distance { 26 | 27 | /** 28 | * mean radius = 6372.0 29 | * 30 | * The Earth's equatorial radius = 6335.437 km. 31 | * 32 | * The Earth's polar radius = 6399.592 km. 33 | * 34 | * 35 | */ 36 | public static final double EARTH_RADIUS_KM = 6372.0; 37 | 38 | /** 39 | * statute miles 40 | */ 41 | public static final double EARTH_RADIUS_MILES = 3963.0; 42 | 43 | /** 44 | * http://mathworld.wolfram.com/GreatCircle.html 45 | * 46 | * and 47 | * 48 | * http://www.mathforum.com/library/drmath/view/51711.html 49 | * 50 | * @return 51 | */ 52 | public static double distance(double lat1, double lng1, double lat2, 53 | double lng2, char unit, int numberOfDigits) { 54 | double a1 = Math.toRadians(lat1); 55 | double b1 = Math.toRadians(lng1); 56 | double a2 = Math.toRadians(lat2); 57 | double b2 = Math.toRadians(lng2); 58 | double d = Math.acos(Math.cos(a1) * Math.cos(b1) * Math.cos(a2) 59 | * Math.cos(b2) + Math.cos(a1) * Math.sin(b1) * Math.cos(a2) 60 | * Math.sin(b2) + Math.sin(a1) * Math.sin(a2)); 61 | 62 | double dist = 0; 63 | if (unit == 'M') { 64 | dist = d * EARTH_RADIUS_MILES; 65 | } else { 66 | dist = d * EARTH_RADIUS_KM; 67 | } 68 | 69 | if (Double.isNaN(dist)) { 70 | // use pytagoras for very small distances, 71 | dist = Math.sqrt(Math.pow(Math.abs(lat1 - lat2), 2) 72 | + Math.pow(Math.abs(lng1 - lng2), 2)); 73 | // as rule of thumb multiply with 110km =1 degree 74 | if (unit == 'M') { 75 | dist *= 69; 76 | } else { 77 | dist *= 110; 78 | } 79 | } 80 | 81 | if (numberOfDigits == 0) { 82 | dist = (int) dist; 83 | } else if (numberOfDigits > 0) { 84 | double factor = Math.pow(10, numberOfDigits); 85 | dist = Math.floor(dist * factor) / factor; 86 | } 87 | return dist; 88 | } 89 | 90 | public static double distanceKM(double lat1, double lng1, double lat2, 91 | double lng2) { 92 | return distance(lat1, lng1, lat2, lng2, 'K', 3); 93 | } 94 | 95 | public static double distanceMiles(double lat1, double lng1, double lat2, 96 | double lng2) { 97 | return distance(lat1, lng1, lat2, lng2, 'M', 3); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /org/geonames/Timezone.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 | import java.util.Date; 20 | 21 | /** 22 | * gmtOffset and dstOffset are computed on the server with the 23 | * {@link java.util.TimeZone} and included in the web service as not all 24 | * geonames users are using java. 25 | * 26 | * @author marc 27 | * 28 | */ 29 | public class Timezone { 30 | 31 | private String timezoneId; 32 | private String countryCode; 33 | private Date time; 34 | private Date sunrise; 35 | private Date sunset; 36 | 37 | @Deprecated 38 | private double gmtOffset; 39 | 40 | @Deprecated 41 | private double dstOffset; 42 | 43 | /** 44 | * the dstOffset as of first of July of current year 45 | * 46 | * @return the dstOffset 47 | */ 48 | @Deprecated 49 | public double getDstOffset() { 50 | return dstOffset; 51 | } 52 | 53 | /** 54 | * @param dstOffset 55 | * the dstOffset to set 56 | */ 57 | public void setDstOffset(double dstOffset) { 58 | this.dstOffset = dstOffset; 59 | } 60 | 61 | /** 62 | * the gmtOffset as of first of January of current year 63 | * 64 | * @return the gmtOffset 65 | */ 66 | @Deprecated 67 | public double getGmtOffset() { 68 | return gmtOffset; 69 | } 70 | 71 | /** 72 | * @param gmtOffset 73 | * the gmtOffset to set 74 | */ 75 | public void setGmtOffset(double gmtOffset) { 76 | this.gmtOffset = gmtOffset; 77 | } 78 | 79 | /** 80 | * the timezoneId (example : "Pacific/Honolulu") 81 | * 82 | * see also {@link java.util.TimeZone} and 83 | * http://www.twinsun.com/tz/tz-link.htm 84 | * 85 | * @return the timezoneId 86 | */ 87 | public String getTimezoneId() { 88 | return timezoneId; 89 | } 90 | 91 | /** 92 | * @param timezoneId 93 | * the timezoneId to set 94 | */ 95 | public void setTimezoneId(String timezoneId) { 96 | this.timezoneId = timezoneId; 97 | } 98 | 99 | /** 100 | * @return the countryCode 101 | */ 102 | public String getCountryCode() { 103 | return countryCode; 104 | } 105 | 106 | /** 107 | * @param countryCode 108 | * the countryCode to set 109 | */ 110 | public void setCountryCode(String countryCode) { 111 | this.countryCode = countryCode; 112 | } 113 | 114 | /** 115 | * @return the time 116 | */ 117 | public Date getTime() { 118 | return time; 119 | } 120 | 121 | /** 122 | * @param time 123 | * the time to set 124 | */ 125 | public void setTime(Date time) { 126 | this.time = time; 127 | } 128 | 129 | /** 130 | * @return the sunrise 131 | */ 132 | public Date getSunrise() { 133 | return sunrise; 134 | } 135 | 136 | /** 137 | * @param sunrise 138 | * the sunrise to set 139 | */ 140 | public void setSunrise(Date sunrise) { 141 | this.sunrise = sunrise; 142 | } 143 | 144 | /** 145 | * @return the sunset 146 | */ 147 | public Date getSunset() { 148 | return sunset; 149 | } 150 | 151 | /** 152 | * @param sunset 153 | * the sunset to set 154 | */ 155 | public void setSunset(Date sunset) { 156 | this.sunset = sunset; 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /org/geonames/StreetSegment.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 street line segment. Includes house number information for the beginning 21 | * and end of the line as well as right and left hand side of the line. 22 | * 23 | * @author marc@geonames 24 | * 25 | */ 26 | public class StreetSegment extends PostalCode { 27 | 28 | private double[] latArray; 29 | 30 | private double[] lngArray; 31 | 32 | /** 33 | * census feature class codes see 34 | * http://www.geonames.org/maps/Census-Feature-Class-Codes.txt 35 | */ 36 | private String cfcc; 37 | 38 | private String name; 39 | 40 | /** 41 | * from address left 42 | */ 43 | private String fraddl; 44 | 45 | /** 46 | * from address right 47 | */ 48 | private String fraddr; 49 | 50 | /** 51 | * to address left 52 | */ 53 | private String toaddl; 54 | 55 | /** 56 | * to address right 57 | */ 58 | private String toaddr; 59 | 60 | /** 61 | * @return the latArray 62 | */ 63 | public double[] getLatArray() { 64 | return latArray; 65 | } 66 | 67 | /** 68 | * @param latArray 69 | * the latArray to set 70 | */ 71 | public void setLatArray(double[] latArray) { 72 | this.latArray = latArray; 73 | } 74 | 75 | /** 76 | * @return the lngArray 77 | */ 78 | public double[] getLngArray() { 79 | return lngArray; 80 | } 81 | 82 | /** 83 | * @param lngArray 84 | * the lngArray to set 85 | */ 86 | public void setLngArray(double[] lngArray) { 87 | this.lngArray = lngArray; 88 | } 89 | 90 | /** 91 | * @return the cfcc 92 | */ 93 | public String getCfcc() { 94 | return cfcc; 95 | } 96 | 97 | /** 98 | * @param cfcc 99 | * the cfcc to set 100 | */ 101 | public void setCfcc(String cfcc) { 102 | this.cfcc = cfcc; 103 | } 104 | 105 | /** 106 | * @return the name 107 | */ 108 | public String getName() { 109 | return name; 110 | } 111 | 112 | /** 113 | * @param name 114 | * the name to set 115 | */ 116 | public void setName(String name) { 117 | this.name = name; 118 | } 119 | 120 | /** 121 | * @return the fraddl 122 | */ 123 | public String getFraddl() { 124 | return fraddl; 125 | } 126 | 127 | /** 128 | * @param fraddl 129 | * the fraddl to set 130 | */ 131 | public void setFraddl(String fraddl) { 132 | this.fraddl = fraddl; 133 | } 134 | 135 | /** 136 | * @return the fraddr 137 | */ 138 | public String getFraddr() { 139 | return fraddr; 140 | } 141 | 142 | /** 143 | * @param fraddr 144 | * the fraddr to set 145 | */ 146 | public void setFraddr(String fraddr) { 147 | this.fraddr = fraddr; 148 | } 149 | 150 | /** 151 | * @return the toaddl 152 | */ 153 | public String getToaddl() { 154 | return toaddl; 155 | } 156 | 157 | /** 158 | * @param toaddl 159 | * the toaddl to set 160 | */ 161 | public void setToaddl(String toaddl) { 162 | this.toaddl = toaddl; 163 | } 164 | 165 | /** 166 | * @return the toaddr 167 | */ 168 | public String getToaddr() { 169 | return toaddr; 170 | } 171 | 172 | /** 173 | * @param toaddr 174 | * the toaddr to set 175 | */ 176 | public void setToaddr(String toaddr) { 177 | this.toaddr = toaddr; 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /org/geonames/PostalCode.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 postal code 21 | * 22 | * @author marc@geonames 23 | * 24 | */ 25 | public class PostalCode { 26 | 27 | private String postalCode; 28 | 29 | private String placeName; 30 | 31 | private String countryCode; 32 | 33 | private double latitude; 34 | 35 | private double longitude; 36 | 37 | private String adminName1; 38 | 39 | private String adminCode1; 40 | 41 | private String adminName2; 42 | 43 | private String adminCode2; 44 | 45 | private String adminName3; 46 | 47 | private String adminCode3; 48 | 49 | private double distance; 50 | 51 | /** 52 | * @return Returns the distance. 53 | */ 54 | public double getDistance() { 55 | return distance; 56 | } 57 | 58 | /** 59 | * @param distance 60 | * The distance to set. 61 | */ 62 | public void setDistance(double distance) { 63 | this.distance = distance; 64 | } 65 | 66 | /** 67 | * @return Returns the adminCode1. 68 | */ 69 | public String getAdminCode1() { 70 | return adminCode1; 71 | } 72 | 73 | /** 74 | * @param adminCode1 75 | * The adminCode1 to set. 76 | */ 77 | public void setAdminCode1(String adminCode1) { 78 | this.adminCode1 = adminCode1; 79 | } 80 | 81 | /** 82 | * @return Returns the adminCode2. 83 | */ 84 | public String getAdminCode2() { 85 | return adminCode2; 86 | } 87 | 88 | /** 89 | * @param adminCode2 90 | * The adminCode2 to set. 91 | */ 92 | public void setAdminCode2(String adminCode2) { 93 | this.adminCode2 = adminCode2; 94 | } 95 | 96 | /** 97 | * @return Returns the adminName1. 98 | */ 99 | public String getAdminName1() { 100 | return adminName1; 101 | } 102 | 103 | /** 104 | * @param adminName1 105 | * The adminName1 to set. 106 | */ 107 | public void setAdminName1(String adminName1) { 108 | this.adminName1 = adminName1; 109 | } 110 | 111 | /** 112 | * @return Returns the adminName2. 113 | */ 114 | public String getAdminName2() { 115 | return adminName2; 116 | } 117 | 118 | /** 119 | * @param adminName2 120 | * The adminName2 to set. 121 | */ 122 | public void setAdminName2(String adminName2) { 123 | this.adminName2 = adminName2; 124 | } 125 | 126 | /** 127 | * @return the adminName3 128 | */ 129 | public String getAdminName3() { 130 | return adminName3; 131 | } 132 | 133 | /** 134 | * @param adminName3 135 | * the adminName3 to set 136 | */ 137 | public void setAdminName3(String adminName3) { 138 | this.adminName3 = adminName3; 139 | } 140 | 141 | /** 142 | * @return the adminCode3 143 | */ 144 | public String getAdminCode3() { 145 | return adminCode3; 146 | } 147 | 148 | /** 149 | * @param adminCode3 150 | * the adminCode3 to set 151 | */ 152 | public void setAdminCode3(String adminCode3) { 153 | this.adminCode3 = adminCode3; 154 | } 155 | 156 | /** 157 | * @return Returns the ISO 3166-1-alpha-2 countryCode. 158 | */ 159 | public String getCountryCode() { 160 | return countryCode; 161 | } 162 | 163 | /** 164 | * @param countryCode 165 | * The ISO 3166-1-alpha-2 countryCode to set. 166 | */ 167 | public void setCountryCode(String countryCode) { 168 | this.countryCode = countryCode; 169 | } 170 | 171 | /** 172 | * latitude in WGS84 173 | * 174 | * @return Returns the latitude. 175 | */ 176 | public double getLatitude() { 177 | return latitude; 178 | } 179 | 180 | /** 181 | * @param latitude 182 | * The latitude to set. 183 | */ 184 | public void setLatitude(double latitude) { 185 | this.latitude = latitude; 186 | } 187 | 188 | /** 189 | * longitude in WGS84 190 | * 191 | * @return Returns the longitude. 192 | */ 193 | public double getLongitude() { 194 | return longitude; 195 | } 196 | 197 | /** 198 | * @param longitude 199 | * The longitude to set. 200 | */ 201 | public void setLongitude(double longitude) { 202 | this.longitude = longitude; 203 | } 204 | 205 | /** 206 | * @return Returns the placeName. 207 | */ 208 | public String getPlaceName() { 209 | return placeName; 210 | } 211 | 212 | /** 213 | * @param placeName 214 | * The placeName to set. 215 | */ 216 | public void setPlaceName(String placeName) { 217 | this.placeName = placeName; 218 | } 219 | 220 | /** 221 | * @return Returns the postalCode. 222 | */ 223 | public String getPostalCode() { 224 | return postalCode; 225 | } 226 | 227 | /** 228 | * @param postalCode 229 | * The postalCode to set. 230 | */ 231 | public void setPostalCode(String postalCode) { 232 | this.postalCode = postalCode; 233 | } 234 | 235 | } 236 | -------------------------------------------------------------------------------- /org/geonames/WikipediaArticle.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 | import java.io.UnsupportedEncodingException; 20 | import java.net.URLEncoder; 21 | import java.util.Comparator; 22 | 23 | /** 24 | * a wikipedia article 25 | * 26 | * @author marc@geonames 27 | * 28 | */ 29 | public class WikipediaArticle { 30 | 31 | private String language; 32 | 33 | private String title; 34 | 35 | private String summary; 36 | 37 | private String wikipediaUrl; 38 | 39 | private String feature; 40 | 41 | private int population; 42 | 43 | private Integer elevation; 44 | 45 | private double latitude; 46 | 47 | private double longitude; 48 | 49 | private String thumbnailImg; 50 | 51 | private int rank; 52 | 53 | /** 54 | * @return Returns the elevation. 55 | */ 56 | public Integer getElevation() { 57 | return elevation; 58 | } 59 | 60 | /** 61 | * @param elevation 62 | * The elevation to set. 63 | */ 64 | public void setElevation(int elevation) { 65 | this.elevation = elevation; 66 | } 67 | 68 | /** 69 | * @return Returns the feature. 70 | */ 71 | public String getFeature() { 72 | return feature; 73 | } 74 | 75 | /** 76 | * @param feature 77 | * The feature to set. 78 | */ 79 | public void setFeature(String feature) { 80 | this.feature = feature; 81 | } 82 | 83 | /** 84 | * @return Returns the language. 85 | */ 86 | public String getLanguage() { 87 | return language; 88 | } 89 | 90 | /** 91 | * @param language 92 | * The language to set. 93 | */ 94 | public void setLanguage(String language) { 95 | this.language = language; 96 | } 97 | 98 | /** 99 | * @return Returns the latitude. 100 | */ 101 | public double getLatitude() { 102 | return latitude; 103 | } 104 | 105 | /** 106 | * @param latitude 107 | * The latitude to set. 108 | */ 109 | public void setLatitude(double latitude) { 110 | this.latitude = latitude; 111 | } 112 | 113 | /** 114 | * @return Returns the longitude. 115 | */ 116 | public double getLongitude() { 117 | return longitude; 118 | } 119 | 120 | /** 121 | * @param longitude 122 | * The longitude to set. 123 | */ 124 | public void setLongitude(double longitude) { 125 | this.longitude = longitude; 126 | } 127 | 128 | /** 129 | * @return Returns the population. 130 | */ 131 | public int getPopulation() { 132 | return population; 133 | } 134 | 135 | /** 136 | * @param population 137 | * The population to set. 138 | */ 139 | public void setPopulation(int population) { 140 | this.population = population; 141 | } 142 | 143 | /** 144 | * @return Returns the summary. 145 | */ 146 | public String getSummary() { 147 | return summary; 148 | } 149 | 150 | /** 151 | * @param summary 152 | * The summary to set. 153 | */ 154 | public void setSummary(String summary) { 155 | this.summary = summary; 156 | } 157 | 158 | /** 159 | * @return Returns the title. 160 | */ 161 | public String getTitle() { 162 | return title; 163 | } 164 | 165 | /** 166 | * @param title 167 | * The title to set. 168 | */ 169 | public void setTitle(String title) { 170 | this.title = title; 171 | } 172 | 173 | /** 174 | * @return Returns the wikipediaUrl. 175 | */ 176 | public String getWikipediaUrl() { 177 | if (wikipediaUrl == null || WebService.isAndroid()) { 178 | String urlTitle = title.replace(' ', '_'); 179 | try { 180 | urlTitle = URLEncoder.encode(urlTitle, "UTF8"); 181 | } catch (UnsupportedEncodingException ex) { 182 | } 183 | String lang = language; 184 | if (WebService.isAndroid()) { 185 | lang += ".m"; 186 | } 187 | return "http://" + lang + ".wikipedia.org/wiki/" + urlTitle; 188 | } 189 | return wikipediaUrl; 190 | } 191 | 192 | /** 193 | * @param wikipediaUrl 194 | * The wikipediaUrl to set. 195 | */ 196 | public void setWikipediaUrl(String wikipediaURL) { 197 | this.wikipediaUrl = wikipediaURL; 198 | } 199 | 200 | /** 201 | * @return the thumbnailImg 202 | */ 203 | public String getThumbnailImg() { 204 | return thumbnailImg; 205 | } 206 | 207 | /** 208 | * @param thumbnailImg 209 | * the thumbnailImg to set 210 | */ 211 | public void setThumbnailImg(String thumbnailImg) { 212 | this.thumbnailImg = thumbnailImg; 213 | } 214 | 215 | /** 216 | * @return the rank 217 | */ 218 | public int getRank() { 219 | return rank; 220 | } 221 | 222 | /** 223 | * @param rank 224 | * the rank to set 225 | */ 226 | public void setRank(int rank) { 227 | this.rank = rank; 228 | } 229 | 230 | public final static Comparator ELEVATION_ORDER = new Comparator() { 231 | public int compare(WikipediaArticle o1, WikipediaArticle o2) { 232 | return Double.compare(o2.elevation, o1.elevation); 233 | } 234 | }; 235 | 236 | public final static Comparator RANK_ORDER = new Comparator() { 237 | public int compare(WikipediaArticle o1, WikipediaArticle o2) { 238 | return Double.compare(o2.rank, o1.rank); 239 | } 240 | }; 241 | } 242 | -------------------------------------------------------------------------------- /org/geonames/WeatherObservation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010 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.util.Date; 20 | 21 | /** 22 | * @author marc 23 | * @since 25.11.2010 24 | * 25 | */ 26 | public class WeatherObservation { 27 | private String observation; 28 | private Date observationTime; 29 | private String stationName; 30 | private String icaoCode; 31 | private String countryCode; 32 | private Integer elevation; 33 | private double latitude; 34 | private double longitude; 35 | private double temperature; 36 | private double dewPoint; 37 | private double humidity; 38 | private String clouds; 39 | private String weatherCondition; 40 | private String windSpeed; 41 | 42 | /** 43 | * @return the observation 44 | */ 45 | public String getObservation() { 46 | return observation; 47 | } 48 | 49 | /** 50 | * @param observation 51 | * the observation to set 52 | */ 53 | public void setObservation(String observation) { 54 | this.observation = observation; 55 | } 56 | 57 | /** 58 | * @return the observationTime 59 | */ 60 | public Date getObservationTime() { 61 | return observationTime; 62 | } 63 | 64 | /** 65 | * @param observationTime 66 | * the observationTime to set 67 | */ 68 | public void setObservationTime(Date observationTime) { 69 | this.observationTime = observationTime; 70 | } 71 | 72 | /** 73 | * @return the stationName 74 | */ 75 | public String getStationName() { 76 | return stationName; 77 | } 78 | 79 | /** 80 | * @param stationName 81 | * the stationName to set 82 | */ 83 | public void setStationName(String stationName) { 84 | this.stationName = stationName; 85 | } 86 | 87 | /** 88 | * @return the icaoCode 89 | */ 90 | public String getIcaoCode() { 91 | return icaoCode; 92 | } 93 | 94 | /** 95 | * @param icaoCode 96 | * the icaoCode to set 97 | */ 98 | public void setIcaoCode(String icaoCode) { 99 | this.icaoCode = icaoCode; 100 | } 101 | 102 | /** 103 | * @return the countryCode 104 | */ 105 | public String getCountryCode() { 106 | return countryCode; 107 | } 108 | 109 | /** 110 | * @param countryCode 111 | * the countryCode to set 112 | */ 113 | public void setCountryCode(String countryCode) { 114 | this.countryCode = countryCode; 115 | } 116 | 117 | /** 118 | * @return the elevation 119 | */ 120 | public Integer getElevation() { 121 | return elevation; 122 | } 123 | 124 | /** 125 | * @param elevation 126 | * the elevation to set 127 | */ 128 | public void setElevation(Integer elevation) { 129 | this.elevation = elevation; 130 | } 131 | 132 | /** 133 | * @return the latitude 134 | */ 135 | public double getLatitude() { 136 | return latitude; 137 | } 138 | 139 | /** 140 | * @param latitude 141 | * the latitude to set 142 | */ 143 | public void setLatitude(double latitude) { 144 | this.latitude = latitude; 145 | } 146 | 147 | /** 148 | * @return the longitude 149 | */ 150 | public double getLongitude() { 151 | return longitude; 152 | } 153 | 154 | /** 155 | * @param longitude 156 | * the longitude to set 157 | */ 158 | public void setLongitude(double longitude) { 159 | this.longitude = longitude; 160 | } 161 | 162 | /** 163 | * @return the temperature 164 | */ 165 | public double getTemperature() { 166 | return temperature; 167 | } 168 | 169 | /** 170 | * @param temperature 171 | * the temperature to set 172 | */ 173 | public void setTemperature(double temperature) { 174 | this.temperature = temperature; 175 | } 176 | 177 | /** 178 | * @return the dewPoint 179 | */ 180 | public double getDewPoint() { 181 | return dewPoint; 182 | } 183 | 184 | /** 185 | * @param dewPoint 186 | * the dewPoint to set 187 | */ 188 | public void setDewPoint(double dewPoint) { 189 | this.dewPoint = dewPoint; 190 | } 191 | 192 | /** 193 | * @return the humidity 194 | */ 195 | public double getHumidity() { 196 | return humidity; 197 | } 198 | 199 | /** 200 | * @param humidity 201 | * the humidity to set 202 | */ 203 | public void setHumidity(double humidity) { 204 | this.humidity = humidity; 205 | } 206 | 207 | /** 208 | * @return the clouds 209 | */ 210 | public String getClouds() { 211 | return clouds; 212 | } 213 | 214 | /** 215 | * @param clouds 216 | * the clouds to set 217 | */ 218 | public void setClouds(String clouds) { 219 | this.clouds = clouds; 220 | } 221 | 222 | /** 223 | * @return the weatherCondition 224 | */ 225 | public String getWeatherCondition() { 226 | return weatherCondition; 227 | } 228 | 229 | /** 230 | * @param weatherCondition 231 | * the weatherCondition to set 232 | */ 233 | public void setWeatherCondition(String weatherCondition) { 234 | this.weatherCondition = weatherCondition; 235 | } 236 | 237 | /** 238 | * @return the windSpeed 239 | */ 240 | public String getWindSpeed() { 241 | return windSpeed; 242 | } 243 | 244 | /** 245 | * @param windSpeed 246 | * the windSpeed to set 247 | */ 248 | public void setWindSpeed(String windSpeed) { 249 | this.windSpeed = windSpeed; 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /org/geonames/PostalCodeSearchCriteria.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 | * search criteria for web services returning postal codes 21 | * 22 | * @author marc@geonames 23 | * 24 | */ 25 | public class PostalCodeSearchCriteria { 26 | 27 | private String postalCode; 28 | 29 | private String placeName; 30 | 31 | private String adminCode1; 32 | 33 | private String countryCode; 34 | 35 | private String countryBias; 36 | 37 | private Double latitude; 38 | 39 | private Double longitude; 40 | 41 | private double radius; 42 | 43 | private Style style; 44 | 45 | private int maxRows; 46 | 47 | private int startRow; 48 | 49 | private boolean isOROperator = false; 50 | 51 | private Boolean isReduced; 52 | 53 | private BoundingBox boundingBox; 54 | 55 | /** 56 | * @return Returns the style. 57 | */ 58 | public Style getStyle() { 59 | return style; 60 | } 61 | 62 | /** 63 | * @param style 64 | * The style to set. 65 | */ 66 | public void setStyle(Style style) { 67 | this.style = style; 68 | } 69 | 70 | /** 71 | * @return Returns the ISO 3166-1-alpha-2 countryCode. 72 | */ 73 | public String getCountryCode() { 74 | return countryCode; 75 | } 76 | 77 | /** 78 | * @param countryCode 79 | * The ISO 3166-1-alpha-2 countryCode to set. 80 | */ 81 | public void setCountryCode(String countryCode) 82 | throws InvalidParameterException { 83 | if (countryCode != null && countryCode.length() != 2) { 84 | throw new InvalidParameterException("invalid country code " 85 | + countryCode); 86 | } 87 | this.countryCode = countryCode; 88 | } 89 | 90 | /** 91 | * @return Returns the latitude. 92 | */ 93 | public Double getLatitude() { 94 | return latitude; 95 | } 96 | 97 | /** 98 | * @param latitude 99 | * The latitude to set. 100 | */ 101 | public void setLatitude(double latitude) throws InvalidParameterException { 102 | if (latitude > 90.0 || latitude < -90.0) { 103 | throw new InvalidParameterException("invalid latitude " + latitude); 104 | } 105 | this.latitude = new Double(latitude); 106 | } 107 | 108 | /** 109 | * @return Returns the longitude. 110 | */ 111 | public Double getLongitude() { 112 | return longitude; 113 | } 114 | 115 | /** 116 | * @param longitude 117 | * The longitude to set. 118 | */ 119 | public void setLongitude(double longitude) throws InvalidParameterException { 120 | if (longitude > 180.0 || longitude < -180.0) { 121 | throw new InvalidParameterException("invalid longitude " 122 | + longitude); 123 | } 124 | this.longitude = new Double(longitude); 125 | } 126 | 127 | /** 128 | * @return Returns the placeName. 129 | */ 130 | public String getPlaceName() { 131 | return placeName; 132 | } 133 | 134 | /** 135 | * @param placeName 136 | * The placeName to set. 137 | */ 138 | public void setPlaceName(String placeName) { 139 | this.placeName = placeName; 140 | } 141 | 142 | /** 143 | * @return Returns the postalCode. 144 | */ 145 | public String getPostalCode() { 146 | return postalCode; 147 | } 148 | 149 | /** 150 | * @param postalCode 151 | * The postalCode to set. 152 | */ 153 | public void setPostalCode(String postalCode) { 154 | this.postalCode = postalCode; 155 | } 156 | 157 | /** 158 | * @return the maxRows 159 | */ 160 | public int getMaxRows() { 161 | return maxRows; 162 | } 163 | 164 | /** 165 | * @param maxRows 166 | * the maxRows to set 167 | */ 168 | public void setMaxRows(int maxRows) { 169 | this.maxRows = maxRows; 170 | } 171 | 172 | /** 173 | * @param isOROperator 174 | * the isOROperator to set 175 | */ 176 | public void setOROperator(boolean isOROperator) { 177 | this.isOROperator = isOROperator; 178 | } 179 | 180 | /** 181 | * @return the isOROperator 182 | */ 183 | public boolean isOROperator() { 184 | return isOROperator; 185 | } 186 | 187 | /** 188 | * @return the adminCode1 189 | */ 190 | public String getAdminCode1() { 191 | return adminCode1; 192 | } 193 | 194 | /** 195 | * @param adminCode1 196 | * the adminCode1 to set 197 | */ 198 | public void setAdminCode1(String adminCode1) { 199 | this.adminCode1 = adminCode1; 200 | } 201 | 202 | /** 203 | * the radius in km to be used for reverse geocoding. 204 | * 205 | * @param radius 206 | * the radius to set 207 | */ 208 | public void setRadius(double radius) { 209 | this.radius = radius; 210 | } 211 | 212 | /** 213 | * @return the radius 214 | */ 215 | public double getRadius() { 216 | return radius; 217 | } 218 | 219 | /** 220 | * @return the countryBias 221 | */ 222 | public String getCountryBias() { 223 | return countryBias; 224 | } 225 | 226 | /** 227 | * @param countryBias 228 | * the countryBias to set 229 | */ 230 | public void setCountryBias(String countryBias) { 231 | this.countryBias = countryBias; 232 | } 233 | 234 | /** 235 | * @return the startRow 236 | */ 237 | public int getStartRow() { 238 | return startRow; 239 | } 240 | 241 | /** 242 | * @param startRow 243 | * the startRow to set 244 | */ 245 | public void setStartRow(int startRow) { 246 | this.startRow = startRow; 247 | } 248 | 249 | /** 250 | * @return the isReduced 251 | */ 252 | public Boolean isReduced() { 253 | return isReduced; 254 | } 255 | 256 | /** 257 | * @param isReduced 258 | * the isReduced to set 259 | */ 260 | public void setIsReduced(Boolean isReduced) { 261 | this.isReduced = isReduced; 262 | } 263 | 264 | /** 265 | * @return the boundingBox 266 | */ 267 | public BoundingBox getBoundingBox() { 268 | return boundingBox; 269 | } 270 | 271 | /** 272 | * @param boundingBox 273 | * the boundingBox to set 274 | */ 275 | public void setBoundingBox(BoundingBox boundingBox) { 276 | this.boundingBox = boundingBox; 277 | } 278 | 279 | } 280 | -------------------------------------------------------------------------------- /org/geonames/ToponymSearchCriteria.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 | import java.util.HashSet; 20 | import java.util.Set; 21 | 22 | /** 23 | * search criteria for web services returning toponyms. 24 | * 25 | * The string parameters do not have to be utf8 encoded. The encoding is done 26 | * transparently in the call to the web service. 27 | * 28 | * The main parameter for the search over all fields is the 'q' parameter. 29 | * 30 | * @see WebService#search 31 | * 32 | * @see search 33 | * webservice documentation< /a> 34 | * 35 | * @author marc@geonames 36 | * 37 | */ 38 | public class ToponymSearchCriteria { 39 | 40 | private String q; 41 | 42 | private String countryCode; 43 | 44 | private Set countryCodes; 45 | 46 | private String countryBias; 47 | 48 | private String continentCode; 49 | 50 | private String name; 51 | 52 | private String nameEquals; 53 | 54 | private String nameStartsWith; 55 | 56 | private String tag; 57 | 58 | private String language; 59 | 60 | private Style style; 61 | 62 | private FeatureClass featureClass; 63 | 64 | private String[] featureCodes; 65 | 66 | private String adminCode1; 67 | 68 | private String adminCode2; 69 | 70 | private String adminCode3; 71 | 72 | private String adminCode4; 73 | 74 | private int maxRows; 75 | 76 | private int startRow; 77 | 78 | private double fuzzy = 1.0; 79 | 80 | private BoundingBox boundingBox; 81 | 82 | /** 83 | * @return Returns the ISO 3166-1-alpha-2 countryCode. 84 | */ 85 | public String getCountryCode() { 86 | return countryCode; 87 | } 88 | 89 | /** 90 | * @param countryCode 91 | * The ISO 3166-1-alpha-2 countryCode to set. 92 | */ 93 | public void setCountryCode(String countryCode) 94 | throws InvalidParameterException { 95 | if (countryCode != null && countryCode.length() != 2) { 96 | throw new InvalidParameterException("invalid country code " 97 | + countryCode); 98 | } 99 | this.countryCode = countryCode; 100 | } 101 | 102 | /** 103 | * @param countryCode 104 | * The ISO 3166-1-alpha-2 countryCode to set. 105 | */ 106 | public void addCountryCode(String countryCode) 107 | throws InvalidParameterException { 108 | if (countryCode != null && countryCode.length() != 2) { 109 | throw new InvalidParameterException("invalid country code " 110 | + countryCode); 111 | } 112 | if (this.countryCodes == null) { 113 | this.countryCodes = new HashSet(); 114 | } 115 | this.countryCodes.add(countryCode); 116 | } 117 | 118 | /** 119 | * @return the countryCodes 120 | */ 121 | public Set getCountryCodes() { 122 | return countryCodes; 123 | } 124 | 125 | /** 126 | * @param countryCodes 127 | * the countryCodes to set 128 | */ 129 | public void setCountryCodes(Set 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&uumlrich");
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 | --------------------------------------------------------------------------------