Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Added pagination support to IConnectionOperations.GetConnections()
Browse files Browse the repository at this point in the history
  • Loading branch information
bbaia committed Mar 19, 2012
1 parent cf4c807 commit 45cd054
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 30 deletions.
Expand Up @@ -52,7 +52,7 @@ static void Main(string[] args)
/*
LinkedInProfile profileById = linkedIn.ProfileOperations.GetUserProfileByIdAsync("xO3SEJSVZN").Result;
LinkedInProfile profileByPublicUrl = linkedIn.ProfileOperations.GetUserProfileByPublicUrlAsync("http://www.linkedin.com/in/bbaia").Result;
IList<LinkedInProfile> connections = linkedIn.ConnectionOperations.GetConnectionsAsync().Result;
LinkedInProfiles connections = linkedIn.ConnectionOperations.GetConnectionsAsync().Result;
NetworkStatistics statistics = linkedIn.ConnectionOperations.GetNetworkStatisticsAsync().Result;
*/
// Consume LinkedIn endpoints that are not covered by the API binding
Expand Down Expand Up @@ -105,7 +105,7 @@ static void Main(string[] args)
/*
LinkedInProfile profileById = linkedIn.ProfileOperations.GetUserProfileById("xO3SEJSVZN");
LinkedInProfile profileByPublicUrl = linkedIn.ProfileOperations.GetUserProfileByPublicUrl("http://www.linkedin.com/in/bbaia");
IList<LinkedInProfile> connections = linkedIn.ConnectionOperations.GetConnections();
LinkedInProfiles connections = linkedIn.ConnectionOperations.GetConnections();
NetworkStatistics statistics = linkedIn.ConnectionOperations.GetNetworkStatistics();
*/
// Consume LinkedIn endpoints that are not covered by the API binding
Expand Down
Expand Up @@ -38,15 +38,27 @@ namespace Spring.Social.LinkedIn.Api
public interface IConnectionOperations
{
#if NET_4_0 || SILVERLIGHT_5
/// <summary>
/// Asynchronously retrieves up to 500 of the 1st-degree connections from the authenticated user's network.
/// </summary>
/// <returns>
/// A <code>Task</code> that represents the asynchronous operation that can return
/// a <see cref="LinkedInProfiles"/> object representing the user's connections.
/// </returns>
/// <exception cref="LinkedInApiException">If there is an error while communicating with LinkedIn.</exception>
Task<LinkedInProfiles> GetConnectionsAsync();

/// <summary>
/// Asynchronously retrieves the 1st-degree connections from the authenticated user's network.
/// </summary>
/// <param name="start">The starting location in the result set. Used with count for pagination.</param>
/// <param name="count">The number of connections to return. The maximum value is 500. Used with start for pagination.</param>
/// <returns>
/// A <code>Task</code> that represents the asynchronous operation that can return
/// a <see cref="LinkedInProfile"/> object representing the user's connections.
/// a <see cref="LinkedInProfiles"/> object representing the user's connections.
/// </returns>
/// <exception cref="LinkedInApiException">If there is an error while communicating with LinkedIn.</exception>
Task<IList<LinkedInProfile>> GetConnectionsAsync();
Task<LinkedInProfiles> GetConnectionsAsync(int start, int count);

/// <summary>
/// Asynchronously retrieves network statistics for the authenticated user.
Expand All @@ -59,14 +71,25 @@ public interface IConnectionOperations
Task<NetworkStatistics> GetNetworkStatisticsAsync();
#else
#if !SILVERLIGHT
/// <summary>
/// Retrieves up to 500 of the 1st-degree connections from the authenticated user's network.
/// </summary>
/// <returns>
/// A <see cref="LinkedInProfiles"/> object representing the user's connections.
/// </returns>
/// <exception cref="LinkedInApiException">If there is an error while communicating with LinkedIn.</exception>
LinkedInProfiles GetConnections();

/// <summary>
/// Retrieves the 1st-degree connections from the authenticated user's network.
/// </summary>
/// <param name="start">The starting location in the result set. Used with count for pagination.</param>
/// <param name="count">The number of connections to return. The maximum value is 500. Used with start for pagination.</param>
/// <returns>
/// A <see cref="LinkedInProfile"/> object representing the user's connections.
/// A <see cref="LinkedInProfiles"/> object representing the user's connections.
/// </returns>
/// <exception cref="LinkedInApiException">If there is an error while communicating with LinkedIn.</exception>
IList<LinkedInProfile> GetConnections();
LinkedInProfiles GetConnections(int start, int count);

/// <summary>
/// Retrieves network statistics for the authenticated user.
Expand All @@ -78,18 +101,33 @@ public interface IConnectionOperations
NetworkStatistics GetNetworkStatistics();
#endif

/// <summary>
/// Asynchronously retrieves up to 500 of the 1st-degree connections from the authenticated user's network.
/// </summary>
/// <param name="operationCompleted">
/// The <code>Action&lt;&gt;</code> to perform when the asynchronous request completes.
/// Provides a <see cref="LinkedInProfiles"/> object representing the user's connections.
/// </param>
/// <returns>
/// A <see cref="RestOperationCanceler"/> instance that allows to cancel the asynchronous operation.
/// </returns>
/// <exception cref="LinkedInApiException">If there is an error while communicating with LinkedIn.</exception>
RestOperationCanceler GetConnectionsAsync(Action<RestOperationCompletedEventArgs<LinkedInProfiles>> operationCompleted);

/// <summary>
/// Asynchronously retrieves the 1st-degree connections from the authenticated user's network.
/// </summary>
/// <param name="start">The starting location in the result set. Used with count for pagination.</param>
/// <param name="count">The number of connections to return. The maximum value is 500. Used with start for pagination.</param>
/// <param name="operationCompleted">
/// The <code>Action&lt;&gt;</code> to perform when the asynchronous request completes.
/// Provides a <see cref="LinkedInProfile"/> object representing the user's connections.
/// Provides a <see cref="LinkedInProfiles"/> object representing the user's connections.
/// </param>
/// <returns>
/// A <see cref="RestOperationCanceler"/> instance that allows to cancel the asynchronous operation.
/// </returns>
/// <exception cref="LinkedInApiException">If there is an error while communicating with LinkedIn.</exception>
RestOperationCanceler GetConnectionsAsync(Action<RestOperationCompletedEventArgs<IList<LinkedInProfile>>> operationCompleted);
RestOperationCanceler GetConnectionsAsync(int start, int count, Action<RestOperationCompletedEventArgs<LinkedInProfiles>> operationCompleted);

/// <summary>
/// Asynchronously retrieves network statistics for the authenticated user.
Expand Down
Expand Up @@ -20,10 +20,14 @@

using System;
using System.Collections.Generic;

#if NET_4_0 || SILVERLIGHT_5
using System.Threading.Tasks;
#endif
#if SILVERLIGHT
using Spring.Collections.Specialized;
#else
using System.Collections.Specialized;
#endif

using Spring.Http;
using Spring.Rest.Client;
Expand All @@ -35,8 +39,11 @@ namespace Spring.Social.LinkedIn.Api.Impl
/// </summary>
/// <author>Robert Drysdale</author>
/// <author>Bruno Baia (.NET)</author>
class ConnectionTemplate : IConnectionOperations
class ConnectionTemplate : AbstractLinkedInOperations, IConnectionOperations
{
private const string ConnectionsUrl = "people/~/connections:(id,first-name,last-name,headline,industry,site-standard-profile-request,public-profile-url,picture-url,summary)?format=json";
private const string NetworkStatsUrl = "people/~/network/network-stats?format=json";

private RestTemplate restTemplate;

public ConnectionTemplate(RestTemplate restTemplate)
Expand All @@ -47,36 +54,60 @@ public ConnectionTemplate(RestTemplate restTemplate)
#region IConnectionOperations Members

#if NET_4_0 || SILVERLIGHT_5
public Task<IList<LinkedInProfile>> GetConnectionsAsync()
public Task<LinkedInProfiles> GetConnectionsAsync()
{
return this.restTemplate.GetForObjectAsync<LinkedInProfiles>(ConnectionsUrl);
}

public Task<LinkedInProfiles> GetConnectionsAsync(int start, int count)
{
return this.restTemplate.GetForObjectAsync<IList<LinkedInProfile>>("people/~/connections:(id,first-name,last-name,headline,industry,site-standard-profile-request,public-profile-url,picture-url,summary)?format=json");
NameValueCollection parameters = new NameValueCollection();
parameters.Add("start", start.ToString());
parameters.Add("count", count.ToString());
return this.restTemplate.GetForObjectAsync<LinkedInProfiles>(this.BuildUrl(ConnectionsUrl, parameters));
}

public Task<NetworkStatistics> GetNetworkStatisticsAsync()
{
return this.restTemplate.GetForObjectAsync<NetworkStatistics>("people/~/network/network-stats?format=json");
return this.restTemplate.GetForObjectAsync<NetworkStatistics>(NetworkStatsUrl);
}
#else
#if !SILVERLIGHT
public IList<LinkedInProfile> GetConnections()
public LinkedInProfiles GetConnections()
{
return this.restTemplate.GetForObject<IList<LinkedInProfile>>("people/~/connections:(id,first-name,last-name,headline,industry,site-standard-profile-request,public-profile-url,picture-url,summary)?format=json");
return this.restTemplate.GetForObject<LinkedInProfiles>(ConnectionsUrl);
}

public LinkedInProfiles GetConnections(int start, int count)
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("start", start.ToString());
parameters.Add("count", count.ToString());
return this.restTemplate.GetForObject<LinkedInProfiles>(this.BuildUrl(ConnectionsUrl, parameters));
}

public NetworkStatistics GetNetworkStatistics()
{
return this.restTemplate.GetForObject<NetworkStatistics>("people/~/network/network-stats?format=json");
return this.restTemplate.GetForObject<NetworkStatistics>(NetworkStatsUrl);
}
#endif

public RestOperationCanceler GetConnectionsAsync(Action<RestOperationCompletedEventArgs<IList<LinkedInProfile>>> operationCompleted)
public RestOperationCanceler GetConnectionsAsync(Action<RestOperationCompletedEventArgs<LinkedInProfiles>> operationCompleted)
{
return this.restTemplate.GetForObjectAsync<LinkedInProfiles>(ConnectionsUrl, operationCompleted);
}

public RestOperationCanceler GetConnectionsAsync(int start, int count, Action<RestOperationCompletedEventArgs<LinkedInProfiles>> operationCompleted)
{
return this.restTemplate.GetForObjectAsync<IList<LinkedInProfile>>("people/~/connections:(id,first-name,last-name,headline,industry,site-standard-profile-request,public-profile-url,picture-url,summary)?format=json", operationCompleted);
NameValueCollection parameters = new NameValueCollection();
parameters.Add("start", start.ToString());
parameters.Add("count", count.ToString());
return this.restTemplate.GetForObjectAsync<LinkedInProfiles>(this.BuildUrl(ConnectionsUrl, parameters), operationCompleted);
}

public RestOperationCanceler GetNetworkStatisticsAsync(Action<RestOperationCompletedEventArgs<NetworkStatistics>> operationCompleted)
{
return this.restTemplate.GetForObjectAsync<NetworkStatistics>("people/~/network/network-stats?format=json", operationCompleted);
return this.restTemplate.GetForObjectAsync<NetworkStatistics>(NetworkStatsUrl, operationCompleted);
}
#endif

Expand Down
Expand Up @@ -33,8 +33,7 @@ class LinkedInProfilesDeserializer : PaginatedResultDeserializer
{
public override object Deserialize(JsonValue json, JsonMapper mapper)
{
JsonValue peopleJson = json.GetValue("people");

JsonValue peopleJson = json.ContainsName("people") ? json.GetValue("people") : json;
LinkedInProfiles profiles = (LinkedInProfiles)base.Deserialize(peopleJson, mapper);
profiles.Profiles = mapper.Deserialize<IList<LinkedInProfile>>(peopleJson);
return profiles;
Expand Down
Expand Up @@ -34,9 +34,9 @@ public virtual object Deserialize(JsonValue json, JsonMapper mapper)
{
PaginatedResult paginatedResult = this.CreatePaginatedResult();

paginatedResult.Start = json.ContainsName("_start") ? json.GetValue<int>("_start") : 0;
paginatedResult.Count = json.ContainsName("_count") ? json.GetValue<int>("_count") : 0;
paginatedResult.Total = json.GetValue<int>("_total");
paginatedResult.Start = json.ContainsName("_start") ? json.GetValue<int>("_start") : 0;
paginatedResult.Count = json.ContainsName("_count") ? json.GetValue<int>("_count") : paginatedResult.Total;

return paginatedResult;
}
Expand Down
Expand Up @@ -63,24 +63,44 @@ public void GetConnections()
.AndRespondWith(JsonResource("Connections"), responseHeaders);

#if NET_4_0 || SILVERLIGHT_5
IList<LinkedInProfile> connections = linkedIn.ConnectionOperations.GetConnectionsAsync().Result;
LinkedInProfiles connections = linkedIn.ConnectionOperations.GetConnectionsAsync().Result;
#else
IList<LinkedInProfile> connections = linkedIn.ConnectionOperations.GetConnections();
LinkedInProfiles connections = linkedIn.ConnectionOperations.GetConnections();
#endif

Assert.AreEqual(4, connections.Count);
AssertProfile(connections[0], "kR0lnX1ll8", "SpringSource Cofounder", "Keith", "Donald", "Computer Software",
Assert.AreEqual(4, connections.Profiles.Count);
AssertProfile(connections.Profiles[0], "kR0lnX1ll8", "SpringSource Cofounder", "Keith", "Donald", "Computer Software",
null, "", null, "http://www.linkedin.com/profile?viewProfile=&key=2526541&authToken=61Sm&authType=name&trk=api*a121026*s129482*", "name:61Sm");
AssertProfile(connections[1], "VRcwcqPCtP", "GM, SpringSource and SVP, Middleware at VMware", "Rod", "Johnson", "Computer Software",
AssertProfile(connections.Profiles[1], "VRcwcqPCtP", "GM, SpringSource and SVP, Middleware at VMware", "Rod", "Johnson", "Computer Software",
null, "", null, "http://www.linkedin.com/profile?viewProfile=&key=210059&authToken=3hU1&authType=name&trk=api*a121026*s129482*", "name:3hU1");
AssertProfile(connections[2], "Ia7uR1OmDB", "Spring and AOP expert; author AspectJ in Action", "Ramnivas", "Laddad", "Computer Software",
AssertProfile(connections.Profiles[2], "Ia7uR1OmDB", "Spring and AOP expert; author AspectJ in Action", "Ramnivas", "Laddad", "Computer Software",
"http://media.linkedin.com/mpr/mprx/0__gnH4Z-585hJSJSu_M6B4RrHCikUf0pu30CB4Rhqg6KwrUI2fUQXnUNVuSXku4j8CYN9cyYH-JuX", "", null,
"http://www.linkedin.com/profile?viewProfile=&key=208994&authToken=P5K9&authType=name&trk=api*a121026*s129482*", "name:P5K9");
AssertProfile(connections[3], "gKEMq4CMdl", "Head of Groovy Development at SpringSource", "Guillaume", "Laforge", "Information Technology and Services",
AssertProfile(connections.Profiles[3], "gKEMq4CMdl", "Head of Groovy Development at SpringSource", "Guillaume", "Laforge", "Information Technology and Services",
"http://media.linkedin.com/mpr/mprx/0_CV5yQ4-Er7cqa-ZZhJziQU1WpS3v2qZZhRliQU1Miez51K74apvKHRbB-iTE71MN_JbCWpT7SdWe", "", null,
"http://www.linkedin.com/profile?viewProfile=&key=822306&authToken=YmIW&authType=name&trk=api*a121026*s129482*", "name:YmIW");
}

[Test]
public void GetPaginatedConnections()
{
mockServer.ExpectNewRequest()
.AndExpectUri("https://api.linkedin.com/v1/people/~/connections:(id,first-name,last-name,headline,industry,site-standard-profile-request,public-profile-url,picture-url,summary)?format=json&start=0&count=4")
.AndExpectMethod(HttpMethod.GET)
.AndRespondWith(JsonResource("Connections"), responseHeaders);

#if NET_4_0 || SILVERLIGHT_5
LinkedInProfiles connections = linkedIn.ConnectionOperations.GetConnectionsAsync(0, 4).Result;
#else
LinkedInProfiles connections = linkedIn.ConnectionOperations.GetConnections(0, 4);
#endif

Assert.AreEqual(0, connections.Start);
Assert.AreEqual(4, connections.Count);
Assert.AreEqual(243, connections.Total);
Assert.AreEqual(4, connections.Profiles.Count);
}

[Test]
public void GetStatistics()
{
Expand Down
Expand Up @@ -91,5 +91,7 @@
"firstName": "Guillaume"
}
],
"_start": 0,
"_count": 4,
"_total": 243
}

0 comments on commit 45cd054

Please sign in to comment.