From 095e3d243717a9a9007f1e7edd86077d150496e4 Mon Sep 17 00:00:00 2001 From: Brendon Date: Mon, 22 Jul 2013 13:00:56 -0600 Subject: [PATCH 1/2] Added PostalCodeNearby --- .../GeoNames/IInvokeGeoNamesServicesTests.cs | 23 +++++++++++++ NGeo.Tests/GeoNames/PostalCodeLookupTests.cs | 22 +++++++++++++ NGeo/GeoNames/GeoNamesClient.cs | 32 +++++++++++++++++++ NGeo/GeoNames/GeoNamesContainer.cs | 6 ++++ NGeo/GeoNames/IConsumeGeoNames.cs | 2 ++ NGeo/GeoNames/IContainGeoNames.cs | 2 ++ NGeo/GeoNames/IInvokeGeoNamesServices.cs | 11 +++++++ NGeo/GeoNames/PostalCode.cs | 8 +++++ NGeo/GeoNames/PostalCodeLookup.cs | 5 +++ NGeo/GeoNames/PostalCodeNearbyResults.cs | 23 +++++++++++++ NGeo/NGeo.csproj | 1 + 11 files changed, 135 insertions(+) create mode 100644 NGeo/GeoNames/PostalCodeNearbyResults.cs diff --git a/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs b/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs index a02a7fb..d85fade 100644 --- a/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs +++ b/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs @@ -41,6 +41,12 @@ public void GeoNames_IInvokeGeoNamesServices_ShouldHaveOperationContractAttribut default(ResultStyle), default(string)) }, }; + var postalnearbyResultsOperations = new Dictionary>> + { + { "findNearbyPostalCodesJSON", p => p.FindNearbyPostalCodes(default(string), default(string), default(double), default(int), + default(ResultStyle), default(string)) }, + }; + var countryResultsOperations = new Dictionary>>> { { "countryInfoJSON", p => p.Countries(default(string)) }, @@ -59,6 +65,7 @@ public void GeoNames_IInvokeGeoNamesServices_ShouldHaveOperationContractAttribut toponymResultsOperations.ShouldHaveOperationContractAttributes(); toponymOperations.ShouldHaveOperationContractAttributes(); codeResultsOperations.ShouldHaveOperationContractAttributes(); + postalCodedCountryResultsOperations.ShouldHaveOperationContractAttributes(); countryResultsOperations.ShouldHaveOperationContractAttributes(); postalCodedCountryResultsOperations.ShouldHaveOperationContractAttributes(); hierarchyOperations.ShouldHaveOperationContractAttributes(); @@ -112,6 +119,22 @@ public void GeoNames_IInvokeGeoNamesServices_LookupPostalCode_ShouldHaveWebInvok attributes[0].BodyStyle.ShouldEqual(WebMessageBodyStyle.Bare); } + [TestMethod] + public void GeoNames_IInvokeGeoNamesServices_FindNearbyPostalCodes_ShouldHaveWebInvokeAttribute() + { + Expression> method = p => p.FindNearbyPostalCodes( + default(string), default(string), default(double), default(int), default(ResultStyle), default(string)); + var attributes = method.GetAttributes(); + + attributes.ShouldNotBeNull(); + attributes.Length.ShouldEqual(1); + attributes[0].UriTemplate.ShouldEqual("findNearbyPostalCodesJSON?postalcode={postalcode}&country={country}&radius={radiusInKm}" + + "&maxRows={maximumResults}&style={resultStyle}&username={userName}"); + attributes[0].RequestFormat.ShouldEqual(WebMessageFormat.Json); + attributes[0].ResponseFormat.ShouldEqual(WebMessageFormat.Json); + attributes[0].BodyStyle.ShouldEqual(WebMessageBodyStyle.Bare); + } + [TestMethod] public void GeoNames_IInvokeGeoNamesServices_PostalCodeCountryInfo_ShouldHaveWebInvokeAttribute() { diff --git a/NGeo.Tests/GeoNames/PostalCodeLookupTests.cs b/NGeo.Tests/GeoNames/PostalCodeLookupTests.cs index 47ac6eb..bfb97de 100644 --- a/NGeo.Tests/GeoNames/PostalCodeLookupTests.cs +++ b/NGeo.Tests/GeoNames/PostalCodeLookupTests.cs @@ -26,6 +26,28 @@ public void GeoNames_PostalCodeLookup_ShouldBePublic() finder.Style.ShouldEqual(ResultStyle.Medium); } + [TestMethod] + public void GeoNames_PostalCodeNearbyLookup_ShouldBePublic() + { + var finder = new PostalCodeLookup + { + PostalCode = "32819", + RadiusInKm = 15, + Country = "US", + UserName = "username", + MaxRows = 2, + Style = ResultStyle.Medium, + }; + + finder.ShouldNotBeNull(); + finder.PostalCode.ShouldEqual("32819"); + finder.RadiusInKm.ShouldEqual(15); + finder.Country.ShouldEqual("US"); + finder.UserName.ShouldNotBeNull(); + finder.MaxRows.ShouldEqual(2); + finder.Style.ShouldEqual(ResultStyle.Medium); + } + [TestMethod] public void GeoNames_PostalCodeLookup_ShouldHaveDefaultValues() { diff --git a/NGeo/GeoNames/GeoNamesClient.cs b/NGeo/GeoNames/GeoNamesClient.cs index 3ec1693..0aea68d 100644 --- a/NGeo/GeoNames/GeoNamesClient.cs +++ b/NGeo/GeoNames/GeoNamesClient.cs @@ -88,6 +88,38 @@ private PostalCodeResults ChannelLookupPostalCode(PostalCodeLookup lookup, int r } } + /// + /// Lookup nearby postal codes. See + /// Official + /// GeoNames findNearbyPostalCodes Documentation for more information. + /// + /// Arguments sent to the GeoNames service. + /// returns a list of postalcodes and places for the lat/lng query as xml document. The result is sorted by distance. For Canada the FSA is returned (first 3 characters of full postal code) + public ReadOnlyCollection FindNearbyPostalCodes(PostalCodeLookup lookup) + { + if (lookup == null) throw new ArgumentNullException("lookup"); + + var response = ChannelFindNearbyPostalCodes(lookup); + var results = response.Items; + return results != null ? new ReadOnlyCollection(results) : null; + } + + private PostalCodeNearbyResults ChannelFindNearbyPostalCodes(PostalCodeLookup lookup, int retry = 0) + { + try + { + var results = Channel.FindNearbyPostalCodes(lookup.PostalCode, lookup.Country, lookup.RadiusInKm, + lookup.MaxRows, lookup.Style, lookup.UserName); + return results; + } + catch (WebException ex) + { + if (retry < RetryLimit && ex.Message.StartsWith(ClosedConnectionMessage, StringComparison.Ordinal)) + return ChannelFindNearbyPostalCodes(lookup, ++retry); + throw; + } + } + /// /// Postal Code Country Info (countries available with min & max postal codes). See /// Official diff --git a/NGeo/GeoNames/GeoNamesContainer.cs b/NGeo/GeoNames/GeoNamesContainer.cs index 8639348..2307046 100644 --- a/NGeo/GeoNames/GeoNamesContainer.cs +++ b/NGeo/GeoNames/GeoNamesContainer.cs @@ -30,6 +30,12 @@ public ReadOnlyCollection LookupPostalCode(PostalCodeLookup lookup) return _client.LookupPostalCode(lookup); } + public ReadOnlyCollection FindNearbyPostalCodes(PostalCodeLookup lookup) + { + if (lookup != null) lookup.UserName = _userName; + return _client.FindNearbyPostalCodes(lookup); + } + public ReadOnlyCollection PostalCodeCountryInfo() { return _client.PostalCodeCountryInfo(_userName); diff --git a/NGeo/GeoNames/IConsumeGeoNames.cs b/NGeo/GeoNames/IConsumeGeoNames.cs index 575a6c4..eab5b12 100644 --- a/NGeo/GeoNames/IConsumeGeoNames.cs +++ b/NGeo/GeoNames/IConsumeGeoNames.cs @@ -9,6 +9,8 @@ public interface IConsumeGeoNames : IDisposable ReadOnlyCollection LookupPostalCode(PostalCodeLookup lookup); + ReadOnlyCollection FindNearbyPostalCodes(PostalCodeLookup lookup); + ReadOnlyCollection PostalCodeCountryInfo(string userName); Toponym Get(int geoNameId, string userName); diff --git a/NGeo/GeoNames/IContainGeoNames.cs b/NGeo/GeoNames/IContainGeoNames.cs index 5c28e0b..60ea039 100644 --- a/NGeo/GeoNames/IContainGeoNames.cs +++ b/NGeo/GeoNames/IContainGeoNames.cs @@ -9,6 +9,8 @@ public interface IContainGeoNames : IDisposable ReadOnlyCollection LookupPostalCode(PostalCodeLookup lookup); + ReadOnlyCollection FindNearbyPostalCodes(PostalCodeLookup lookup); + ReadOnlyCollection PostalCodeCountryInfo(); Toponym Get(int geoNameId); diff --git a/NGeo/GeoNames/IInvokeGeoNamesServices.cs b/NGeo/GeoNames/IInvokeGeoNamesServices.cs index 406f6f2..5482341 100644 --- a/NGeo/GeoNames/IInvokeGeoNamesServices.cs +++ b/NGeo/GeoNames/IInvokeGeoNamesServices.cs @@ -39,6 +39,17 @@ Results FindNearbyPlaceName(double latitude, double longitude, string l PostalCodeResults LookupPostalCode(string postalcode, string country, int maximumResults, ResultStyle resultStyle, string userName); + [OperationContract(Name = "findNearbyPostalCodesJSON")] + [WebInvoke( + UriTemplate = "findNearbyPostalCodesJSON?postalcode={postalcode}&country={country}&radius={radiusInKm}" + + "&maxRows={maximumResults}&style={resultStyle}&username={userName}", + RequestFormat = WebMessageFormat.Json, + ResponseFormat = WebMessageFormat.Json, + BodyStyle = WebMessageBodyStyle.Bare + )] + PostalCodeNearbyResults FindNearbyPostalCodes(string postalcode, string country, double radiusInKm, + int maximumResults, ResultStyle resultStyle, string userName); + [OperationContract(Name = "postalCodeCountryInfoJSON")] [WebInvoke( UriTemplate = "postalCodeCountryInfoJSON?username={userName}", diff --git a/NGeo/GeoNames/PostalCode.cs b/NGeo/GeoNames/PostalCode.cs index f529af6..89f41e2 100644 --- a/NGeo/GeoNames/PostalCode.cs +++ b/NGeo/GeoNames/PostalCode.cs @@ -20,6 +20,14 @@ public class PostalCode [DataMember(Name = "lng")] public double Longitude { get; internal set; } + [DataMember(Name = "distance")] + public string Distance + { + get { return _distance; } + internal set { _distance = value.ToNullIfEmptyOrWhiteSpace(); } + } + private string _distance; + [DataMember(Name = "adminCode1")] public string Admin1Code { get; internal set; } diff --git a/NGeo/GeoNames/PostalCodeLookup.cs b/NGeo/GeoNames/PostalCodeLookup.cs index 83825f0..7cd4ed4 100644 --- a/NGeo/GeoNames/PostalCodeLookup.cs +++ b/NGeo/GeoNames/PostalCodeLookup.cs @@ -24,6 +24,11 @@ public PostalCodeLookup() /// public string Country { get; set; } + /// + /// Find place names in this radius. + /// + public double RadiusInKm { get; set; } + /// /// GeoNames services require a user name. /// diff --git a/NGeo/GeoNames/PostalCodeNearbyResults.cs b/NGeo/GeoNames/PostalCodeNearbyResults.cs new file mode 100644 index 0000000..250d45e --- /dev/null +++ b/NGeo/GeoNames/PostalCodeNearbyResults.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace NGeo.GeoNames +{ + [DataContract] + public sealed class PostalCodeNearbyResults : IEnumerable + { + [DataMember(Name = "postalCodes")] + internal List Items { get; set; } + + public IEnumerator GetEnumerator() + { + return Items.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/NGeo/NGeo.csproj b/NGeo/NGeo.csproj index 002aa97..3ac0621 100644 --- a/NGeo/NGeo.csproj +++ b/NGeo/NGeo.csproj @@ -64,6 +64,7 @@ + From 3efc831c189804cd64116510db44a9e79c1c912c Mon Sep 17 00:00:00 2001 From: Brendon Date: Mon, 22 Jul 2013 13:10:23 -0600 Subject: [PATCH 2/2] Added PostalCodeNearby --- NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs b/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs index d85fade..3ae29e4 100644 --- a/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs +++ b/NGeo.Tests/GeoNames/IInvokeGeoNamesServicesTests.cs @@ -41,7 +41,7 @@ public void GeoNames_IInvokeGeoNamesServices_ShouldHaveOperationContractAttribut default(ResultStyle), default(string)) }, }; - var postalnearbyResultsOperations = new Dictionary>> + var postalNearbyResultsOperations = new Dictionary>> { { "findNearbyPostalCodesJSON", p => p.FindNearbyPostalCodes(default(string), default(string), default(double), default(int), default(ResultStyle), default(string)) }, @@ -65,7 +65,7 @@ public void GeoNames_IInvokeGeoNamesServices_ShouldHaveOperationContractAttribut toponymResultsOperations.ShouldHaveOperationContractAttributes(); toponymOperations.ShouldHaveOperationContractAttributes(); codeResultsOperations.ShouldHaveOperationContractAttributes(); - postalCodedCountryResultsOperations.ShouldHaveOperationContractAttributes(); + postalNearbyResultsOperations.ShouldHaveOperationContractAttributes(); countryResultsOperations.ShouldHaveOperationContractAttributes(); postalCodedCountryResultsOperations.ShouldHaveOperationContractAttributes(); hierarchyOperations.ShouldHaveOperationContractAttributes();